openerp-community-reviewer team mailing list archive
-
openerp-community-reviewer team
-
Mailing list archive
-
Message #01686
lp:~camptocamp/carriers-deliveries/7.0-add-delivery_carrier_label_laposte-yvr into lp:carriers-deliveries
Yannick Vaucher @ Camptocamp has proposed merging lp:~camptocamp/carriers-deliveries/7.0-add-delivery_carrier_label_laposte-yvr into lp:carriers-deliveries with lp:~camptocamp/carriers-deliveries/7.0-add-base_delivery_carrier_label-yvr as a prerequisite.
Requested reviews:
Guewen Baconnier @ Camptocamp (gbaconnier-c2c)
For more details, see:
https://code.launchpad.net/~camptocamp/carriers-deliveries/7.0-add-delivery_carrier_label_laposte-yvr/+merge/196839
This module implements Swiss PostLogics "Barcode" webservice to generate shipping labels.
http://www.poste.ch/post-barcode-cug.htm
* it connects to WebService using suds SOAP client
* it permits to retrieve all services provided by Postlogistics with translations in available languages with an update button in settings
* options are filtered in carrier in order to improve user experience
Depends on following MP:
https://code.launchpad.net/~camptocamp/carriers-deliveries/7.0-add-base_delivery_carrier_label-yvr/+merge/196753
--
https://code.launchpad.net/~camptocamp/carriers-deliveries/7.0-add-delivery_carrier_label_laposte-yvr/+merge/196839
Your team Stock and Logistic Core Editors is subscribed to branch lp:carriers-deliveries.
=== added directory 'delivery_carrier_label_postlogistics'
=== added file 'delivery_carrier_label_postlogistics/__init__.py'
--- delivery_carrier_label_postlogistics/__init__.py 1970-01-01 00:00:00 +0000
+++ delivery_carrier_label_postlogistics/__init__.py 2013-11-27 09:43:32 +0000
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Yannick Vaucher
+# Copyright 2013 Camptocamp SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from . import company
+from . import res_config
+from . import postlogistics
+from . import delivery
+from . import stock
=== added file 'delivery_carrier_label_postlogistics/__openerp__.py'
--- delivery_carrier_label_postlogistics/__openerp__.py 1970-01-01 00:00:00 +0000
+++ delivery_carrier_label_postlogistics/__openerp__.py 2013-11-27 09:43:32 +0000
@@ -0,0 +1,111 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Yannick Vaucher
+# Copyright 2013 Camptocamp SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+{'name': 'PostLogistics Labels WebService',
+ 'version': '1.0',
+ 'author': 'Camptocamp',
+ 'maintainer': 'Camptocamp',
+ 'category': 'version',
+ 'complexity': 'normal',
+ 'depends': ['base_delivery_carrier_label'],
+ 'description': """
+PostLogistics Labels WebService
+===============================
+
+Description
+-----------
+
+This module uses `PostLogistics BarCodes WebService`_ to generate labels
+for your Delivery Orders.
+
+It adds a `Create label` button on Delivery Orders.
+A generated label will be an attachement of your Delivery Order.
+
+To see it, please install documents module.
+
+You can create multiple delivery method to match your diffent package types.
+
+
+Configuration
+-------------
+
+.. important::
+ A "Swiss Post Business customer" account is required to use this module.
+
+ See `Swiss Post E-logistics`_
+
+
+To configure:
+
+* Go to `Configurations -> Settings -> Postlogistics`
+* Set your login informations
+* launch the Update PostLogistics Services
+
+This will load available services and generate carrier options.
+
+Now you can create a carrier method for PostLogistics WebService:
+
+* First choose a Service group and save
+* Add a Mandatory Carrier option using a Basic Service
+* Save Carrier Method (this will update filters to show you only
+ compatible services)
+* Then add other `Optional as default` and `Optional` carrier option
+ from listed
+* Additional Service and Delivery instructions
+
+.. _PostLogistics BarCodes WebService: http://www.poste.ch/post-startseite/post-geschaeftskunden/post-logistik/post-e-log/post-e-log-webservices.htm
+.. _Swiss Post E-logistics: http://www.poste.ch/en/post-startseite/post-geschaeftskunden/post-logistik/post-e-log.htm
+
+Technical references
+--------------------
+
+`"Barcode" web service documentation`_
+
+.. _"Barcode" web service documentation: http://www.poste.ch/post-barcode-cug.htm
+
+Contributors
+------------
+
+* Yannick Vaucher <yannick.vaucher@xxxxxxxxxxxxxx>
+
+----
+
+*TODO*:
+
+* *Add onchange to improve carrier method creation*
+* *Default options*
+* *Identify attachement as label*
+* *Better License management*
+""",
+ 'website': 'http://www.camptocamp.com/',
+ 'data': ['res_partner_data.xml',
+ 'delivery_data.xml',
+ 'delivery_view.xml',
+ 'res_config_view.xml',
+ ],
+ 'tests': [],
+ 'installable': True,
+ 'auto_install': False,
+ 'license': 'AGPL-3',
+ 'application': True,
+ 'external_dependencies': {
+ 'python': ['suds'],
+ }
+ }
=== added file 'delivery_carrier_label_postlogistics/company.py'
--- delivery_carrier_label_postlogistics/company.py 1970-01-01 00:00:00 +0000
+++ delivery_carrier_label_postlogistics/company.py 2013-11-27 09:43:32 +0000
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Yannick Vaucher
+# Copyright 2013 Camptocamp SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from openerp.osv import orm, fields
+from openerp.tools import file_open
+
+
+class ResCompany(orm.Model):
+ _inherit = 'res.company'
+
+ def _get_wsdl_url(self, cr, uid, ids, field_name, arg, context=None):
+ wsdl_file, wsdl_path = file_open('delivery_carrier_label_laposte/data/barcode_v2_1.wsdl', pathinfo=True)
+ wsdl_url = 'file://' + wsdl_path
+ res = dict.fromkeys(ids, wsdl_url)
+ return res
+
+ _columns = {
+ 'postlogistics_wsdl_url': fields.function(
+ _get_wsdl_url,
+ string='WSDL URL',
+ type='char'),
+ 'postlogistics_username': fields.char('Username'),
+ 'postlogistics_password': fields.char('Password'),
+ # XXX improve license management
+ 'postlogistics_license_less_1kg': fields.char('License less than 1kg'),
+ 'postlogistics_license_more_1kg': fields.char('License more than 1kg'),
+ 'postlogistics_license_vinolog': fields.char('License VinoLog'),
+ 'postlogistics_logo': fields.binary('Company logo for PostLogistics'),
+ 'postlogistics_office': fields.char('Post office'),
+ }
=== added directory 'delivery_carrier_label_postlogistics/data'
=== added file 'delivery_carrier_label_postlogistics/data/barcode_v2_1.wsdl'
--- delivery_carrier_label_postlogistics/data/barcode_v2_1.wsdl 1970-01-01 00:00:00 +0000
+++ delivery_carrier_label_postlogistics/data/barcode_v2_1.wsdl 2013-11-27 09:43:32 +0000
@@ -0,0 +1,249 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<definitions name="Barcode"
+ targetNamespace="https://www.mypostbusiness.ch/wsbc/barcode/v2_1"
+ xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="https://www.mypostbusiness.ch/wsbc/barcode/v2_1"
+ xmlns:barcode="https://www.mypostbusiness.ch/wsbc/barcode/v2_1/types"
+ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
+ <types>
+ <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <xsd:import
+ namespace="https://www.mypostbusiness.ch/wsbc/barcode/v2_1/types"
+ schemaLocation="barcode_v2_1.xsd" />
+ </xsd:schema>
+ </types>
+
+ <message name="ValidateCombination">
+ <part name="body" element="barcode:ValidateCombination" />
+ </message>
+ <message name="ValidateCombinationResponse">
+ <part name="body" element="barcode:ValidateCombinationResponse" />
+ </message>
+
+ <message name="GenerateLabel">
+ <part name="body" element="barcode:GenerateLabel" />
+ </message>
+ <message name="GenerateLabelResponse">
+ <part name="body" element="barcode:GenerateLabelResponse" />
+ </message>
+
+ <message name="GenerateSingleBarcodes">
+ <part name="body" element="barcode:GenerateSingleBarcodes" />
+ </message>
+ <message name="GenerateSingleBarcodesResponse">
+ <part name="body" element="barcode:GenerateSingleBarcodesResponse" />
+ </message>
+
+ <message name="ReadServiceGroups">
+ <part name="body" element="barcode:ReadServiceGroups" />
+ </message>
+ <message name="ReadServiceGroupsResponse">
+ <part name="body" element="barcode:ReadServiceGroupsResponse" />
+ </message>
+
+ <message name="ReadBasicServices">
+ <part name="body" element="barcode:ReadBasicServices" />
+ </message>
+ <message name="ReadBasicServicesResponse">
+ <part name="body" element="barcode:ReadBasicServicesResponse" />
+ </message>
+
+ <message name="ReadAllowedServicesByFrankingLicense">
+ <part name="body" element="barcode:ReadAllowedServicesByFrankingLicense" />
+ </message>
+ <message name="ReadAllowedServicesByFrankingLicenseResponse">
+ <part name="body"
+ element="barcode:ReadAllowedServicesByFrankingLicenseResponse" />
+ </message>
+
+ <message name="ReadAdditionalServices">
+ <part name="body" element="barcode:ReadAdditionalServices" />
+ </message>
+ <message name="ReadAdditionalServicesResponse">
+ <part name="body" element="barcode:ReadAdditionalServicesResponse" />
+ </message>
+
+ <message name="ReadDeliveryInstructions">
+ <part name="body" element="barcode:ReadDeliveryInstructions" />
+ </message>
+ <message name="ReadDeliveryInstructionsResponse">
+ <part name="body" element="barcode:ReadDeliveryInstructionsResponse" />
+ </message>
+
+ <message name="ReadLabelLayouts">
+ <part name="body" element="barcode:ReadLabelLayouts" />
+ </message>
+ <message name="ReadLabelLayoutsResponse">
+ <part name="body" element="barcode:ReadLabelLayoutsResponse" />
+ </message>
+
+ <message name="GenerateBarcode">
+ <part name="body" element="barcode:GenerateBarcode" />
+ </message>
+ <message name="GenerateBarcodeResponse">
+ <part name="body" element="barcode:GenerateBarcodeResponse" />
+ </message>
+
+ <portType name="BarcodePortType">
+
+ <operation name="ValidateCombination">
+ <input message="tns:ValidateCombination" />
+ <output message="tns:ValidateCombinationResponse" />
+ </operation>
+
+ <operation name="GenerateLabel">
+ <input message="tns:GenerateLabel" />
+ <output message="tns:GenerateLabelResponse" />
+ </operation>
+
+ <operation name="GenerateSingleBarcodes">
+ <input message="tns:GenerateSingleBarcodes" />
+ <output message="tns:GenerateSingleBarcodesResponse" />
+ </operation>
+
+ <operation name="ReadServiceGroups">
+ <input message="tns:ReadServiceGroups" />
+ <output message="tns:ReadServiceGroupsResponse" />
+ </operation>
+
+ <operation name="ReadBasicServices">
+ <input message="tns:ReadBasicServices" />
+ <output message="tns:ReadBasicServicesResponse" />
+ </operation>
+
+ <operation name="ReadAllowedServicesByFrankingLicense">
+ <input message="tns:ReadAllowedServicesByFrankingLicense" />
+ <output message="tns:ReadAllowedServicesByFrankingLicenseResponse" />
+ </operation>
+
+ <operation name="ReadAdditionalServices">
+ <input message="tns:ReadAdditionalServices" />
+ <output message="tns:ReadAdditionalServicesResponse" />
+ </operation>
+
+ <operation name="ReadDeliveryInstructions">
+ <input message="tns:ReadDeliveryInstructions" />
+ <output message="tns:ReadDeliveryInstructionsResponse" />
+ </operation>
+
+ <operation name="ReadLabelLayouts">
+ <input message="tns:ReadLabelLayouts" />
+ <output message="tns:ReadLabelLayoutsResponse" />
+ </operation>
+
+ <operation name="GenerateBarcode">
+ <input message="tns:GenerateBarcode" />
+ <output message="tns:GenerateBarcodeResponse" />
+ </operation>
+
+ </portType>
+ <binding name="BarcodeSoapBinding" type="tns:BarcodePortType">
+ <soap:binding style="document"
+ transport="http://schemas.xmlsoap.org/soap/http" />
+
+ <operation name="ValidateCombination">
+ <soap:operation soapAction="ValidateCombination" />
+ <input>
+ <soap:body use="literal" />
+ </input>
+ <output>
+ <soap:body use="literal" />
+ </output>
+ </operation>
+
+ <operation name="GenerateLabel">
+ <soap:operation soapAction="GenerateLabel" />
+ <input>
+ <soap:body use="literal" />
+ </input>
+ <output>
+ <soap:body use="literal" />
+ </output>
+ </operation>
+
+ <operation name="GenerateSingleBarcodes">
+ <soap:operation soapAction="GenerateSingleBarcodes" />
+ <input>
+ <soap:body use="literal" />
+ </input>
+ <output>
+ <soap:body use="literal" />
+ </output>
+ </operation>
+
+ <operation name="ReadServiceGroups">
+ <soap:operation soapAction="ReadServiceGroups" />
+ <input>
+ <soap:body use="literal" />
+ </input>
+ <output>
+ <soap:body use="literal" />
+ </output>
+ </operation>
+
+ <operation name="ReadBasicServices">
+ <soap:operation soapAction="ReadBasicServices" />
+ <input>
+ <soap:body use="literal" />
+ </input>
+ <output>
+ <soap:body use="literal" />
+ </output>
+ </operation>
+
+ <operation name="ReadAllowedServicesByFrankingLicense">
+ <soap:operation soapAction="ReadAllowedServicesByFrankingLicense" />
+ <input>
+ <soap:body use="literal" />
+ </input>
+ <output>
+ <soap:body use="literal" />
+ </output>
+ </operation>
+
+ <operation name="ReadAdditionalServices">
+ <soap:operation soapAction="ReadAdditionalServices" />
+ <input>
+ <soap:body use="literal" />
+ </input>
+ <output>
+ <soap:body use="literal" />
+ </output>
+ </operation>
+
+ <operation name="ReadDeliveryInstructions">
+ <soap:operation soapAction="ReadDeliveryInstructions" />
+ <input>
+ <soap:body use="literal" />
+ </input>
+ <output>
+ <soap:body use="literal" />
+ </output>
+ </operation>
+
+ <operation name="ReadLabelLayouts">
+ <soap:operation soapAction="ReadLabelLayouts" />
+ <input>
+ <soap:body use="literal" />
+ </input>
+ <output>
+ <soap:body use="literal" />
+ </output>
+ </operation>
+
+ <operation name="GenerateBarcode">
+ <soap:operation soapAction="GenerateBarcode" />
+ <input>
+ <soap:body use="literal" />
+ </input>
+ <output>
+ <soap:body use="literal" />
+ </output>
+ </operation>
+
+ </binding>
+ <service name="BarcodeService">
+ <port name="BarcodePort" binding="tns:BarcodeSoapBinding">
+ <soap:address location="https://www.mypostbusiness.ch/wsbc/barcode/v2_1" />
+ </port>
+ </service>
+</definitions>
\ No newline at end of file
=== added file 'delivery_carrier_label_postlogistics/data/barcode_v2_1.xsd'
--- delivery_carrier_label_postlogistics/data/barcode_v2_1.xsd 1970-01-01 00:00:00 +0000
+++ delivery_carrier_label_postlogistics/data/barcode_v2_1.xsd 2013-11-27 09:43:32 +0000
@@ -0,0 +1,1198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns="https://www.mypostbusiness.ch/wsbc/barcode/v2_1/types"
+ targetNamespace="https://www.mypostbusiness.ch/wsbc/barcode/v2_1/types"
+ elementFormDefault="qualified" attributeFormDefault="unqualified">
+
+ <!-- 5.4 Use Case Validiere Kombination (Seite 12) -->
+ <xs:element name="ValidateCombination">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Language" type="Language" />
+ <xs:element name="Envelope">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="LabelDefinition" type="LabelDefinition" />
+ <xs:element name="Data">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Provider">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Sending">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Item"
+ type="ValidateCombinationItem"
+ maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name="ValidateCombinationItem">
+ <xs:sequence>
+ <xs:element name="ItemID" type="ItemIDType" minOccurs="0" />
+ <xs:element name="Attributes" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PRZL" type="PRZLType"
+ minOccurs="1" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Country" type="CountryType"
+ minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:element name="ValidateCombinationResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Envelope">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="LabelDefinition" type="LabelDefinition" />
+ <xs:element name="Data">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Provider">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Sending">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Item"
+ type="ResponseItem" maxOccurs="unbounded" />
+ <xs:element name="Country"
+ type="CountryType" minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- 5.5 Use Case Generiere Adressträger (Seite 34) -->
+ <xs:element name="GenerateLabel">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Language" type="Language" />
+ <xs:element name="Envelope">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="LabelDefinition" type="GenerateLabelDefinition" />
+ <xs:element name="FileInfos" type="GenerateLabelFileInfos" />
+ <xs:element name="Data" type="LabelData" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name="GenerateLabelDefinition">
+ <xs:complexContent>
+ <xs:extension base="LabelDefinition">
+ <xs:sequence>
+ <xs:element name="PrintAddresses" type="PrintAddressesType" />
+ <xs:element name="ImageFileType" type="ImageFileType" />
+ <xs:element name="ImageResolution" type="xs:int" />
+ <xs:element name="PrintPreview" type="xs:boolean" />
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:simpleType name="PrintAddressesType">
+ <xs:annotation>
+ <xs:documentation>Enumeration to indicated wheter addresses are
+ printet or not.</xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="None">
+ <xs:annotation>
+ <xs:documentation>No Addresses are printed.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="OnlyRecipient">
+ <xs:annotation>
+ <xs:documentation>Only recipient's address is printed.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="OnlyCustomer">
+ <xs:annotation>
+ <xs:documentation>Only customer's address is printed.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="RecipientAndCustomer">
+ <xs:annotation>
+ <xs:documentation>Recipient and customer addresses are
+ printed.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="GenerateLabelFileInfos">
+ <xs:sequence>
+ <xs:element name="FrankingLicense" type="FrankingLicenseType" />
+ <xs:element name="PpFranking" type="xs:boolean"
+ default="false" />
+ <xs:element name="Customer" type="GenerateLabelCustomer" />
+ <xs:element name="CustomerSystem" type="CustomerSystemType"
+ minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="GenerateLabelCustomer">
+ <xs:sequence>
+ <xs:element name="Name1" type="CustomerAddressLineType" />
+ <xs:element name="Name2" minOccurs="0"
+ type="CustomerAddressLineType" />
+ <xs:element name="Street" type="CustomerAddressLineType" />
+ <xs:element name="POBox" type="CustomerAddressLineType"
+ minOccurs="0" />
+ <xs:element name="ZIP">
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:totalDigits value="6" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="City" type="CustomerAddressLineType" />
+ <xs:element name="Country" type="CountryType"
+ minOccurs="0" />
+ <xs:element name="Logo" type="xs:base64Binary"
+ minOccurs="0" />
+ <xs:element name="LogoFormat" minOccurs="0">
+ <xs:simpleType>
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="3" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="DomicilePostOffice" minOccurs="0">
+ <xs:simpleType>
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="35" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:element name="GenerateLabelResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Envelope">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="LabelDefinition"
+ type="GenerateLabelResponseDefinition" />
+ <xs:element name="Data">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Provider">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Sending">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="SendingID"
+ type="SendingIDType" minOccurs="0" />
+ <xs:element name="Item"
+ type="LabelResponseItem" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name="GenerateLabelResponseDefinition">
+ <xs:complexContent>
+ <xs:extension base="GenerateLabelDefinition">
+ <xs:sequence>
+ <xs:element name="ColorPrintRequired" type="xs:boolean" />
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="LabelResponseItem">
+ <xs:complexContent>
+ <xs:extension base="ResponseItem">
+ <xs:sequence>
+ <xs:element name="IdentCode" type="IdentCodeType"
+ minOccurs="0" />
+ <xs:element name="Label" type="xs:base64Binary"
+ minOccurs="0" />
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <!-- WSBC 2.1 FaFo 14.1 Labellayout BC -->
+ <xs:element name="GenerateSingleBarcodes">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Language" type="Language" />
+ <xs:element name="Envelope">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="BarcodeDefinition" type="SingleBarcodesDefinition" />
+ <xs:element name="FileInfos" type="SingleBarcodesFileInfos" />
+ <xs:element name="Data" type="LabelData" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name="SingleBarcodesDefinition">
+ <xs:sequence>
+ <xs:element name="ImageFileType" type="ImageFileType" />
+ <xs:element name="ImageResolution" type="xs:int" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="SingleBarcodesFileInfos">
+ <xs:sequence>
+ <xs:element name="FrankingLicense" type="FrankingLicenseType" />
+ <xs:element name="PpFranking" type="xs:boolean"
+ default="false" />
+ <xs:element name="Customer" type="SingleBarcodesCustomer" />
+ <xs:element name="CustomerSystem" type="CustomerSystemType"
+ minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="SingleBarcodesCustomer">
+ <xs:sequence>
+ <xs:element name="Name1" type="CustomerAddressLineType" />
+ <xs:element name="Name2" minOccurs="0"
+ type="CustomerAddressLineType" />
+ <xs:element name="Street" type="CustomerAddressLineType" />
+ <xs:element name="POBox" type="CustomerAddressLineType"
+ minOccurs="0" />
+ <xs:element name="ZIP">
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:totalDigits value="6" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="City" type="CustomerAddressLineType" />
+ <xs:element name="Country" type="CountryType"
+ minOccurs="0" />
+ <xs:element name="DomicilePostOffice" minOccurs="0">
+ <xs:simpleType>
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="35" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:element name="GenerateSingleBarcodesResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Envelope">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="BarcodeDefinition"
+ type="SingleBarcodesResponseDefinition" />
+ <xs:element name="Data">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Provider">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Sending">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="SendingID"
+ type="SendingIDType" minOccurs="0" />
+ <xs:element name="Item"
+ type="SingleBarcodesResponseItem"
+ maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name="SingleBarcodesResponseDefinition">
+ <xs:complexContent>
+ <xs:extension base="SingleBarcodesDefinition">
+ <xs:sequence>
+ <xs:element name="ColorPrintRequired" type="xs:boolean" />
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="SingleBarcodesResponseItem">
+ <xs:complexContent>
+ <xs:extension base="ResponseItem">
+ <xs:sequence>
+ <xs:element name="IdentCode" type="IdentCodeType"
+ minOccurs="0" />
+ <xs:element name="Barcodes" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Barcode" type="xs:base64Binary"
+ maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <!-- Common datatypes for generate label and generate single barcodes -->
+ <xs:simpleType name="CustomerAddressLineType">
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="25" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="LabelData">
+ <xs:sequence>
+ <xs:element name="Provider">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Sending">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="SendingID" type="SendingIDType"
+ minOccurs="0" />
+ <xs:element name="Item" type="Item"
+ maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:simpleType name="SendingIDType">
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="50" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="Item">
+ <xs:sequence>
+ <xs:element name="ItemID" type="ItemIDType" minOccurs="0" />
+ <xs:element name="ItemNumber" type="ItemNumberType"
+ minOccurs="0" />
+ <xs:element name="IdentCode" type="IdentCodeType"
+ minOccurs="0" />
+ <xs:element name="Recipient" type="Recipient" />
+ <xs:element name="AdditionalINFOS" minOccurs="0">
+ <xs:annotation>
+ <xs:documentation>ehem. REC_Data bei V2.1 und 2.0
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="AdditionalData" type="AdditionalData"
+ maxOccurs="50" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Attributes" type="ServiceCodeAttributes"
+ minOccurs="0" />
+ <xs:element name="Notification" type="Notification"
+ minOccurs="0" maxOccurs="15">
+ <xs:annotation>
+ <xs:documentation>Zusatzinformationen für Dienstleistung
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:simpleType name="ItemNumberType">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[0-9]{1,8}" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="Recipient">
+ <xs:sequence>
+ <xs:element name="PostIdent" minOccurs="0">
+ <xs:simpleType>
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="15" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="Title" type="RecipientAddressType"
+ minOccurs="0" />
+ <xs:element name="PersonallyAddressed" type="xs:boolean"
+ minOccurs="0" />
+ <xs:element name="Name1" type="RecipientAddressType" />
+ <xs:element name="FirstName" type="RecipientAddressType"
+ minOccurs="0" />
+ <xs:element name="Name2" type="RecipientAddressType"
+ minOccurs="0" />
+ <xs:element name="Street" type="RecipientAddressType"
+ minOccurs="0" />
+ <xs:element name="HouseNo" minOccurs="0">
+ <xs:simpleType>
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="5" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="POBox" type="RecipientAddressType"
+ minOccurs="0" />
+ <xs:element name="FloorNo" minOccurs="0">
+ <xs:simpleType>
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="5" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="MailboxNo" minOccurs="0">
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:totalDigits value="10" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="ZIP" minOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="10" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="City" type="RecipientAddressType" />
+ <xs:element name="Country" type="CountryType"
+ minOccurs="0" />
+ <xs:element name="Phone" type="PhoneNumberType"
+ minOccurs="0" />
+ <xs:element name="Mobile" type="PhoneNumberType"
+ minOccurs="0" />
+ <xs:element name="EMail" type="EMailAddressType"
+ minOccurs="0" />
+ <xs:element name="LabelAddress" type="LabelAddress"
+ minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="LabelAddress">
+ <xs:annotation>
+ <xs:documentation>optional, used to declare a specific address on
+ the label. if omitted, the address data of
+ the recipient is taken. Useful if the address data of the recipient
+ exceeds the length of the label.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="NameLine" type="RecipientAddressType" />
+ <xs:element name="AddressLine" type="RecipientAddressType" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:simpleType name="RecipientAddressType">
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="35" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="AdditionalData">
+ <xs:sequence>
+ <xs:element name="Type">
+ <xs:simpleType>
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="35" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="Value">
+ <xs:simpleType>
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="50" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="ServiceCodeAttributes">
+ <xs:sequence>
+ <xs:element name="PRZL" type="PRZLType" minOccurs="1"
+ maxOccurs="unbounded" />
+ <xs:element name="Amount" type="AmountType" minOccurs="0" />
+ <xs:element name="FreeText" minOccurs="0">
+ <xs:simpleType>
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="34" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="DeliveryDate" type="xs:date"
+ minOccurs="0" />
+ <xs:element name="ParcelNo" type="ParcelAmountType"
+ minOccurs="0" />
+ <xs:element name="ParcelTotal" type="ParcelAmountType"
+ minOccurs="0" />
+ <xs:element name="DeliveryPlace" minOccurs="0">
+ <xs:simpleType>
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="35" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="ProClima" type="xs:boolean"
+ minOccurs="0" />
+ <xs:element name="Dimensions" type="Dimensions"
+ minOccurs="0" />
+ <xs:element name="UNNumbers" type="UNNumbers"
+ minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:simpleType name="ParcelAmountType">
+ <xs:restriction base="xs:int">
+ <xs:minInclusive value="0" />
+ <xs:maxInclusive value="99" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="Dimensions">
+ <xs:annotation>
+ <xs:documentation>Represents the Dimensions attribute of the
+ DataTransfer.</xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="Weight">
+ <xs:annotation>
+ <xs:documentation>Weight in gramms.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:totalDigits value="5" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="UNNumbers">
+ <xs:annotation>
+ <xs:documentation>Represents the UN Numbers for the additional
+ service LQ (limited quantities).
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="UNNumber" minOccurs="0" maxOccurs="unbounded">
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:totalDigits value="4" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Notification">
+ <xs:all>
+ <xs:element name="Communication" type="Communication" />
+ <xs:element name="Service">
+ <xs:annotation>
+ <xs:documentation>Avisierungs-Code, welcher die Avisierung
+ bezeichnet.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:totalDigits value="20" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="FreeText1" minOccurs="0">
+ <xs:annotation>
+ <xs:documentation>Individueller Text 1 für Avisierung.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="160" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="FreeText2" minOccurs="0">
+ <xs:annotation>
+ <xs:documentation>Individueller Text 2 für Avisierung.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="512" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="Language" type="Language" />
+ </xs:all>
+ <xs:attribute name="Type" type="NotificationType" use="required">
+ <xs:annotation>
+ <xs:documentation>Angabe des Medium</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+
+ <xs:simpleType name="NotificationType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="EMAIL" />
+ <xs:enumeration value="SMS" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="Communication">
+ <xs:choice>
+ <xs:element name="Email" type="EMailAddressType" />
+ <xs:element name="Mobile" type="PhoneNumberType" />
+ </xs:choice>
+ </xs:complexType>
+
+ <!-- 5.6 Use Case Lese Dienstleistungsgruppen -->
+ <xs:element name="ReadServiceGroups">
+ <xs:complexType>
+ <xs:choice>
+ <xs:element name="Language" type="Language" />
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="ReadServiceGroupsResponse">
+ <xs:complexType>
+ <xs:choice>
+ <xs:element name="ServiceGroup" type="ServiceGroup"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="Errors" type="ErrorsType"
+ minOccurs="0" />
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- FAfo-10.1 FTA Page 65 Lese BL einer FRLZ -->
+ <xs:element name="ReadAllowedServicesByFrankingLicense">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="FrankingLicense" type="FrankingLicenseType"
+ minOccurs="1" />
+ <xs:element name="Language" type="Language" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- FAfo-10.1 FTA Page 65 Lese BL einer FRLZ -->
+ <xs:element name="ReadAllowedServicesByFrankingLicenseResponse">
+ <xs:complexType>
+ <xs:choice>
+ <!-- DLGs -->
+ <xs:element name="ServiceGroups" type="ReadAllowedServicesServiceGroups"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="Errors" type="ErrorsType"
+ minOccurs="0" />
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name="ReadAllowedServicesServiceGroups">
+ <xs:sequence>
+ <xs:element name="ServiceGroup" type="ServiceGroup" />
+ <xs:element name="BasicService" type="BasicService"
+ maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <!-- 5.7 Use Case Lese Basisleistungen -->
+ <xs:element name="ReadBasicServices">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Language" type="Language" />
+ <xs:element name="ServiceGroupID" type="xs:int" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="ReadBasicServicesResponse">
+ <xs:complexType>
+ <xs:choice>
+ <xs:element name="BasicService" type="BasicService"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="Errors" type="ErrorsType"
+ minOccurs="0" />
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- 5.8 Use Case Lese Zusatzleistungen -->
+ <xs:element name="ReadAdditionalServices">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Language" type="Language" />
+ <xs:element name="PRZL" type="PRZLType" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="ReadAdditionalServicesResponse">
+ <xs:complexType>
+ <xs:choice>
+ <xs:element name="AdditionalService" type="ServiceCode"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="Errors" type="ErrorsType"
+ minOccurs="0" />
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- 5.9 Use Case Lese Zustellanweisungen -->
+ <xs:element name="ReadDeliveryInstructions">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Language" type="Language" />
+ <xs:element name="PRZL" type="PRZLType" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="ReadDeliveryInstructionsResponse">
+ <xs:complexType>
+ <xs:choice>
+ <xs:element name="DeliveryInstructions" type="ServiceCode"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="Errors" type="ErrorsType"
+ minOccurs="0" />
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- 5.10 Use Case Lese Darstellungsarten -->
+ <xs:element name="ReadLabelLayouts">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Language" type="Language" />
+ <xs:element name="PRZL" type="PRZLType" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="ReadLabelLayoutsResponse">
+ <xs:complexType>
+ <xs:choice>
+ <xs:element name="LabelLayout" type="LabelLayoutResponse"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="Errors" type="ErrorsType"
+ minOccurs="0" />
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name="LabelLayoutResponse">
+ <xs:sequence>
+ <xs:element name="LabelLayout" type="LabelLayoutType" />
+ <xs:element name="MaxServices" type="xs:int" />
+ <xs:element name="MaxDeliveryInstructions" type="xs:int" />
+ <xs:element name="FreeTextAllowed" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:element name="GenerateBarcode">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Language" type="Language" />
+ <xs:element name="BarcodeDefinition" type="BarcodeDefinition" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="GenerateBarcodeResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Data" type="BarcodeResponseData"
+ minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name="BarcodeResponseData">
+ <xs:sequence>
+ <xs:element name="Barcode" type="xs:base64Binary"
+ minOccurs="0" />
+ <xs:element name="DeliveryNoteRef" minOccurs="0">
+ <xs:annotation>
+ <xs:documentation>Lieferscheinnummer Barcodeliste BMZ (128-er
+ Klartext-Barcode)</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:maxLength value="50" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="BarcodeDefinition" type="BarcodeDefinition" />
+ <xs:element name="ColorPrintRequired" type="xs:boolean" />
+ <xs:element name="Errors" type="ErrorsType" minOccurs="0" />
+ <xs:element name="Warnings" type="WarningsType"
+ minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="BarcodeDefinition">
+ <xs:annotation>
+ <xs:documentation>Represents a BarcodeDefinition for the
+ GenerateBarcode Service.</xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="BarcodeType" type="BarcodeType" />
+ <xs:element name="ImageFileType" type="ImageFileType" />
+ <xs:element name="ImageResolution" type="xs:int" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:simpleType name="BarcodeType">
+ <xs:annotation>
+ <xs:documentation>Enumeration of the different barcode types.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="LSO_1">
+ <xs:annotation>
+ <xs:documentation>LSO-1 barcode for delivery notes online.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="LSO_2">
+ <xs:annotation>
+ <xs:documentation>LSO-2 barcode for delivery notes online.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="LSO_3">
+ <xs:annotation>
+ <xs:documentation>LSO-3 barcode for delivery notes online.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <!-- **************************** Gloabal used datastructures **************************** -->
+ <xs:complexType name="ServiceCode">
+ <xs:annotation>
+ <xs:documentation>Represents a service code.</xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="PRZL" type="PRZLType" />
+ <xs:element name="Description" type="DescriptionType" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="BasicService">
+ <xs:annotation>
+ <xs:documentation>Represents a Basic Service.</xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="PRZL" type="PRZLType" minOccurs="0"
+ maxOccurs="unbounded" />
+ <xs:element name="Description" type="DescriptionType" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="ServiceGroup">
+ <xs:annotation>
+ <xs:documentation>Represents a Service Group.</xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="ServiceGroupID" type="xs:int" />
+ <xs:element name="Description" type="DescriptionType" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:simpleType name="DescriptionType">
+ <xs:annotation>
+ <xs:documentation>A common type for descriptions.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string"> <!-- only used as response type -->
+ <xs:maxLength value="255" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="LabelDefinition">
+ <xs:sequence>
+ <xs:element name="LabelLayout" type="LabelLayoutType" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="ResponseItem">
+ <xs:sequence>
+ <xs:element name="ItemID" type="ItemIDType" minOccurs="0" />
+ <xs:element name="Errors" type="ErrorsType" minOccurs="0" />
+ <xs:element name="Warnings" type="WarningsType"
+ minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="ErrorsType">
+ <xs:annotation>
+ <xs:documentation>Structure containing a list of occurred business
+ errors.</xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="Error" type="MessageType" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="WarningsType">
+ <xs:annotation>
+ <xs:documentation>Structure containing a list of occurred business
+ warnings.</xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="Warning" type="MessageType"
+ maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="MessageType">
+ <xs:annotation>
+ <xs:documentation>Represents a business error or warning. Does not
+ include technical errors, those are
+ handled by SOAP faults.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="Code" type="MessageCodeType" />
+ <xs:element name="Message" type="MessageTextType" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:simpleType name="MessageCodeType">
+ <xs:annotation>
+ <xs:documentation>Five digit error/warning code. Error codes
+ starts with a "E" and warning codes
+ with a "W".
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[W,E]{1}[0-9]{4}" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="MessageTextType">
+ <xs:annotation>
+ <xs:documentation>Descriptive text in user's language for the
+ occurred business warning/error.
+ </xs:documentation>
+ </xs:annotation>
+ <!-- only used as response type -->
+ <xs:restriction base="xs:string">
+ <xs:maxLength value="500" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="Language">
+ <xs:annotation>
+ <xs:documentation>Represents the end-users language. The service
+ returns all localized texts including
+ error-messages in the selected language.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="de">
+ <xs:annotation>
+ <xs:documentation>German</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="fr">
+ <xs:annotation>
+ <xs:documentation>French</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="it">
+ <xs:annotation>
+ <xs:documentation>Italien</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="en">
+ <xs:annotation>
+ <xs:documentation>English</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="ItemIDType">
+ <xs:annotation>
+ <xs:documentation>Unique identifier for a specific item defined by
+ the consumer.</xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="200" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="PRZLType">
+ <xs:annotation>
+ <xs:documentation>Identifies a PRZL.</xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[a-zA-Z,0-9]{1,7}" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="PhoneNumberType">
+ <xs:annotation>
+ <xs:documentation>Defines a valid phone number.</xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="20" />
+ <xs:minLength value="9" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="CountryType">
+ <xs:annotation>
+ <xs:documentation>The ISO country code.</xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[a-zA-Z]{2}" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="AmountType">
+ <xs:annotation>
+ <xs:documentation>The amount for COD.</xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:float">
+ <xs:minInclusive value="0.00" />
+ <xs:maxInclusive value="99999.99" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="EMailAddressType">
+ <xs:annotation>
+ <xs:documentation>The email address.</xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="CommonPatternStringType">
+ <xs:maxLength value="160" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="LabelLayoutType">
+ <xs:annotation>
+ <xs:documentation>Defines valid layouts.</xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[a-zA-Z,0-9]{2}" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="ImageFileType">
+ <xs:annotation>
+ <xs:documentation>Defines valid formats of images.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[a-zA-Z,0-9]{1,5}" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="FrankingLicenseType">
+ <xs:annotation>
+ <xs:documentation>Defines a franking license.</xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[a-zA-Z,0-9]{4}" />
+ <xs:pattern value="[0-9]{6}" />
+ <xs:pattern value="[0-9]{8}" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="CustomerSystemType">
+ <xs:restriction base="CommonPatternStringType">
+ <xs:pattern value="[a-zA-Z,0-9,\s]{1,255}" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="IdentCodeType">
+ <xs:annotation>
+ <xs:documentation>IdentCode is only a valid input for
+ Post-internal applications. For Post-external
+ applications the IdentCode must not be set.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="CommonPatternStringType">
+ <xs:pattern value="[0-9]{18}" />
+ <xs:pattern value="[0-9]{23}" />
+ <xs:pattern value="[a-zA-Z,0-9]{13}" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="CommonPatternStringType">
+ <xs:annotation>
+ <xs:documentation>Excludes unsupported characters.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="([^\*|\\|\{|\}|\[|\]|=|>|<])*" />
+ </xs:restriction>
+ </xs:simpleType>
+
+
+</xs:schema>
\ No newline at end of file
=== added file 'delivery_carrier_label_postlogistics/data/post-barcode-handbuch.pdf'
Binary files delivery_carrier_label_postlogistics/data/post-barcode-handbuch.pdf 1970-01-01 00:00:00 +0000 and delivery_carrier_label_postlogistics/data/post-barcode-handbuch.pdf 2013-11-27 09:43:32 +0000 differ
=== added file 'delivery_carrier_label_postlogistics/delivery.py'
--- delivery_carrier_label_postlogistics/delivery.py 1970-01-01 00:00:00 +0000
+++ delivery_carrier_label_postlogistics/delivery.py 2013-11-27 09:43:32 +0000
@@ -0,0 +1,213 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Yannick Vaucher
+# Copyright 2013 Camptocamp SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from openerp.osv import orm, fields
+
+
+class PostlogisticsServiceGroup(orm.Model):
+ _name = 'postlogistics.service.group'
+ _description = 'PostLogistics Service Group'
+
+ _columns = {
+ 'name': fields.char('Description', translate=True, required=True),
+ 'group_extid': fields.integer('Group ID', required=True),
+ }
+
+ _sql_constraints = [
+ ('group_extid_uniq', 'unique(group_extid)',
+ "A service group ID must be unique.")
+ ]
+
+
+POSTLOGISTIC_TYPES = [
+ ('label_layout', 'Label Layout'),
+ ('output_format', 'Output Format'),
+ ('resolution', 'Output Resolution'),
+ ('basic', 'Basic Service'),
+ ('additional', 'Additional Service'),
+ ('delivery', 'Delivery Instructions')
+]
+
+
+class DeliveryCarrierTemplateOption(orm.Model):
+ """ Set name translatable and add service group """
+ _inherit = 'delivery.carrier.template.option'
+
+ _columns = {
+ 'name': fields.char('Name', size=64, translate=True),
+ 'postlogistics_service_group_id': fields.many2one(
+ 'postlogistics.service.group',
+ string='PostLogistics Service Group'),
+ 'postlogistics_type': fields.selection(
+ POSTLOGISTIC_TYPES,
+ string="PostLogistics option type"),
+ # relation tables to manage compatiblity between basic services
+ # and other services
+ 'postlogistics_basic_service_ids': fields.many2many(
+ 'delivery.carrier.template.option',
+ 'postlogistics_compatibility_service_rel',
+ 'service_id', 'basic_service_id',
+ string="Basic Services",
+ domain=[('postlogistics_type', '=', 'basic')],
+ help="List of basic service for which this service is compatible"),
+ 'postlogistics_additonial_service_ids': fields.many2many(
+ 'delivery.carrier.template.option',
+ 'postlogistics_compatibility_service_rel',
+ 'basic_service_id', 'service_id',
+ string="Compatible Additional Services",
+ domain=[('postlogistics_type', '=', 'additional')]),
+ 'postlogistics_delivery_instruction_ids': fields.many2many(
+ 'delivery.carrier.template.option',
+ 'postlogistics_compatibility_service_rel',
+ 'basic_service_id', 'service_id',
+ string="Compatible Delivery Instructions",
+ domain=[('postlogistics_type', '=', 'delivery')]),
+ }
+
+ _defaults = {
+ 'postlogistics_type': False,
+ }
+
+
+class DeliveryCarrierOption(orm.Model):
+ """ Set name translatable and add service group """
+ _inherit = 'delivery.carrier.option'
+
+ _columns = {
+ 'name': fields.char('Name', size=64, translate=True),
+ # to repeat carrier allowed option ids to filter domain set by
+ # default from view
+ 'allowed_option_ids': fields.related(
+ 'carrier_id', 'allowed_option_ids', type='many2many',
+ relation='delivery.carrier.template.option',
+ string='Allowed and compatible options',
+ readonly=True),
+ }
+
+
+class DeliveryCarrier(orm.Model):
+ """ Add service group """
+ _inherit = 'delivery.carrier'
+
+ def _get_carrier_type_selection(self, cr, uid, context=None):
+ """ To inherit to add carrier type """
+ res = super(DeliveryCarrier, self)._get_carrier_type_selection(cr, uid, context=context)
+ res.append(('postlogistics', 'Postlogistics'))
+ return res
+
+ def _get_basic_service_id(self, cr, uid, ids, field_names, arg, context=None):
+ """ Search in all options for the postlogistic basic service if set """
+ res = dict.fromkeys(ids, False)
+ ir_model_data_obj = self.pool.get('ir.model.data')
+
+ xmlid = 'delivery_carrier_label_laposte', 'postlogistics'
+ postlogistics_partner = ir_model_data_obj.get_object(
+ cr, uid, *xmlid, context=context)
+
+ for carrier in self.browse(cr, uid, ids, context=context):
+ if not carrier.partner_id.id == postlogistics_partner.id:
+ continue
+
+ option_ids = [opt.tmpl_option_id.id for opt
+ in carrier.available_option_ids
+ if opt.postlogistics_type == 'basic']
+ if not option_ids:
+ continue
+ res[carrier.id] = option_ids[0]
+ return res
+
+ def _get_allowed_option_ids(self, cr, uid, ids, field_names, arg, context=None):
+ """ Return a list of possible options
+
+ A domain would be too complicated.
+
+ We do this to ensure the user first select a basic service. And
+ then he adds additional services.
+
+ :return: {carrier_id: [ids]}
+
+ """
+ res = dict.fromkeys(ids, [])
+ option_template_obj = self.pool.get('delivery.carrier.template.option')
+ ir_model_data_obj = self.pool.get('ir.model.data')
+
+ xmlid = 'delivery_carrier_label_laposte', 'postlogistics'
+ postlogistics_partner = ir_model_data_obj.get_object(
+ cr, uid, *xmlid, context=context)
+
+ for carrier in self.browse(cr, uid, ids, context=context):
+ allowed_ids = []
+ if not carrier.partner_id.id == postlogistics_partner.id:
+ continue
+ service_group_id = carrier.postlogistics_service_group_id.id
+ if service_group_id:
+ # if there are no basic option set. Show basic options
+ basic_service_id = carrier.postlogistics_basic_service_id.id
+ if not basic_service_id:
+ service_ids = option_template_obj.search(
+ cr, uid,
+ [('postlogistics_service_group_id' ,'=', service_group_id)],
+ context=context)
+ else:
+ service_ids = option_template_obj.search(
+ cr, uid,
+ [('postlogistics_basic_service_ids' ,'in', basic_service_id)],
+ context=context)
+ allowed_ids.extend(service_ids)
+
+ # Allows to set multiple optional single option in order to
+ # let the user select them
+ single_option_types = ['label_layout', 'output_format', 'resolution']
+ selected_single_options = [opt.tmpl_option_id.postlogistics_type
+ for opt in carrier.available_option_ids
+ if opt.postlogistics_type in single_option_types
+ and opt.state in ['mandatory']]
+ if selected_single_options != single_option_types:
+ service_ids = option_template_obj.search(
+ cr, uid,
+ [('postlogistics_type', 'in', single_option_types),
+ ('postlogistics_type', 'not in', selected_single_options)],
+ context=context)
+ allowed_ids.extend(service_ids)
+ res[carrier.id] = allowed_ids
+ return res
+
+ _columns = {
+ 'type': fields.selection(
+ _get_carrier_type_selection, 'Type',
+ help="Carrier type (combines several delivery methods)"),
+ 'postlogistics_service_group_id': fields.many2one(
+ 'postlogistics.service.group',
+ string='PostLogistics Service Group',
+ help="Service group defines the available options for "
+ "this delivery method."),
+ 'postlogistics_basic_service_id': fields.function(
+ _get_basic_service_id, type='many2one',
+ relation='delivery.carrier.template.option',
+ string='PostLogistics Service Group',
+ help="Basic Service defines the available "
+ "additional options for this delivery method",
+ readonly=True),
+ 'allowed_option_ids': fields.function(
+ _get_allowed_option_ids, type="many2many",
+ relation='delivery.carrier.template.option',
+ string='Allowed options',
+ help="Compute allowed options according to selected options."),
+ }
=== added file 'delivery_carrier_label_postlogistics/delivery_data.xml'
--- delivery_carrier_label_postlogistics/delivery_data.xml 1970-01-01 00:00:00 +0000
+++ delivery_carrier_label_postlogistics/delivery_data.xml 2013-11-27 09:43:32 +0000
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data noupdate="1">
+
+ <!-- Label layouts -->
+ <record id="postlogistics_layout_option_a7" model="delivery.carrier.template.option">
+ <field name="name">Format A7</field>
+ <field name="code">A7</field>
+ <field name="postlogistics_type">label_layout</field>
+ <field name="partner_id" ref="postlogistics"></field>
+ </record>
+
+ <record id="postlogistics_layout_option_a6" model="delivery.carrier.template.option">
+ <field name="name">Format A6</field>
+ <field name="code">A6</field>
+ <field name="postlogistics_type">label_layout</field>
+ <field name="partner_id" ref="postlogistics"></field>
+ </record>
+
+ <record id="postlogistics_layout_option_a5" model="delivery.carrier.template.option">
+ <field name="name">Format A5</field>
+ <field name="code">A5</field>
+ <field name="postlogistics_type">label_layout</field>
+ <field name="partner_id" ref="postlogistics"></field>
+ </record>
+
+ <record id="postlogistics_layout_option_fe" model="delivery.carrier.template.option">
+ <field name="name">Format FE</field>
+ <field name="code">FE</field>
+ <field name="postlogistics_type">label_layout</field>
+ <field name="partner_id" ref="postlogistics"></field>
+ </record>
+
+
+ <!-- Output formats -->
+ <record id="postlogistics_output_format_option_eps" model="delivery.carrier.template.option">
+ <field name="name">EPS</field>
+ <field name="code">EPS</field>
+ <field name="postlogistics_type">output_format</field>
+ <field name="partner_id" ref="postlogistics"></field>
+ </record>
+
+ <record id="postlogistics_output_format_option_gif" model="delivery.carrier.template.option">
+ <field name="name">GIF</field>
+ <field name="code">GIF</field>
+ <field name="postlogistics_type">output_format</field>
+ <field name="partner_id" ref="postlogistics"></field>
+ </record>
+
+ <record id="postlogistics_output_format_option_jpg" model="delivery.carrier.template.option">
+ <field name="name">JPG</field>
+ <field name="code">JPG</field>
+ <field name="postlogistics_type">output_format</field>
+ <field name="partner_id" ref="postlogistics"></field>
+ </record>
+
+ <record id="postlogistics_output_format_option_png" model="delivery.carrier.template.option">
+ <field name="name">PNG</field>
+ <field name="code">PNG</field>
+ <field name="postlogistics_type">output_format</field>
+ <field name="partner_id" ref="postlogistics"></field>
+ </record>
+
+ <record id="postlogistics_output_format_option_pdf" model="delivery.carrier.template.option">
+ <field name="name">PDF</field>
+ <field name="code">PDF</field>
+ <field name="postlogistics_type">output_format</field>
+ <field name="partner_id" ref="postlogistics"></field>
+ </record>
+
+ <record id="postlogistics_output_format_option_spdf" model="delivery.carrier.template.option">
+ <field name="name">sPDF</field>
+ <field name="code">sPDF</field>
+ <field name="postlogistics_type">output_format</field>
+ <field name="partner_id" ref="postlogistics"></field>
+ </record>
+
+ <record id="postlogistics_output_format_option_zpl2" model="delivery.carrier.template.option">
+ <field name="name">ZPL2</field>
+ <field name="code">ZPL2</field>
+ <field name="postlogistics_type">output_format</field>
+ <field name="partner_id" ref="postlogistics"></field>
+ </record>
+
+
+ <!-- resolutions -->
+ <record id="postlogistics_output_resolution_option_200ppp" model="delivery.carrier.template.option">
+ <field name="name">200 ppp</field>
+ <field name="code">200</field>
+ <field name="postlogistics_type">resolution</field>
+ <field name="partner_id" ref="postlogistics"></field>
+ </record>
+
+ <record id="postlogistics_output_resolution_option_300ppp" model="delivery.carrier.template.option">
+ <field name="name">300 ppp</field>
+ <field name="code">300</field>
+ <field name="postlogistics_type">resolution</field>
+ <field name="partner_id" ref="postlogistics"></field>
+ </record>
+
+ <record id="postlogistics_output_resolution_option_600ppp" model="delivery.carrier.template.option">
+ <field name="name">600 ppp</field>
+ <field name="code">600</field>
+ <field name="postlogistics_type">resolution</field>
+ <field name="partner_id" ref="postlogistics"></field>
+ </record>
+ </data>
+</openerp>
=== added file 'delivery_carrier_label_postlogistics/delivery_view.xml'
--- delivery_carrier_label_postlogistics/delivery_view.xml 1970-01-01 00:00:00 +0000
+++ delivery_carrier_label_postlogistics/delivery_view.xml 2013-11-27 09:43:32 +0000
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+ <data>
+
+ <!-- INHERITED VIEW FOR THE OBJECT : delivery_carrier_template_option -->
+ <record id="delivery_carrier_template_option_view_form" model="ir.ui.view">
+ <field name="name">delivery_base.delivery_carrier_option.view_form</field>
+ <field name="model">delivery.carrier.template.option</field>
+ <field name="inherit_id" ref="base_delivery_carrier_label.delivery_carrier_template_option_view_form"/>
+ <field name="arch" type="xml">
+ <field name="name" position="after">
+ <field name="postlogistics_service_group_id"/>
+ </field>
+ </field>
+ </record>
+
+ <record id="delivery_carrier_template_option_view_tree" model="ir.ui.view">
+ <field name="name">delivery_base.delivery_carrier_template_option.view_tree</field>
+ <field name="model">delivery.carrier.template.option</field>
+ <field name="inherit_id" ref="base_delivery_carrier_label.delivery_carrier_template_option_view_tree"/>
+ <field name="arch" type="xml">
+ <field name="name" position="after">
+ <field name="postlogistics_service_group_id"/>
+ </field>
+ </field>
+ </record>
+
+ <!-- INHERITED VIEW FOR THE OBJECT : delivery_carrier_option -->
+ <record id="delivery_carrier_option_view_form" model="ir.ui.view">
+ <field name="name">delivery_base.delivery_carrier_option.view_form</field>
+ <field name="model">delivery.carrier.option</field>
+ <field name="inherit_id" ref="base_delivery_carrier_label.delivery_carrier_option_view_form" />
+ <field name="arch" type="xml">
+ <field name="tmpl_option_id" position="before">
+ <field name="carrier_id" invisible="1"/>
+ <field name="allowed_option_ids" invisible="1"/>
+ </field>
+ <field name="tmpl_option_id" position="attributes">
+ <attribute name="domain">['|', ('partner_id', '!=', %(delivery_carrier_label_laposte.postlogistics)d), ('id', 'in', allowed_option_ids[0][2])]</attribute>
+ </field>
+ </field>
+ </record>
+
+ <!-- INHERITED VIEW FOR THE OBJECT : delivery.carrier -->
+ <record id="view_delivery_carrier_form" model="ir.ui.view">
+ <field name="name">delivery_base.delivery.carrier.view_form</field>
+ <field name="model">delivery.carrier</field>
+ <field name="inherit_id" ref="base_delivery_carrier_label.view_delivery_carrier_form" />
+ <field name="arch" type="xml">
+ <field name="type" position="after">
+ <field name="postlogistics_service_group_id" attrs="{'invisible': [('type', '!=', 'postlogistics')], 'required': [('type', '!=', 'postlogistics')]}"/>
+ <field name="allowed_option_ids" invisible="1"/>
+ </field>
+ <field name="available_option_ids" position="attributes">
+ <attribute name="context">{'default_carrier_id': active_id, 'default_allowed_option_ids': allowed_option_ids}</attribute>
+ </field>
+ </field>
+ </record>
+
+ </data>
+</openerp>
=== added directory 'delivery_carrier_label_postlogistics/i18n'
=== added directory 'delivery_carrier_label_postlogistics/postlogistics'
=== added file 'delivery_carrier_label_postlogistics/postlogistics/__init__.py'
--- delivery_carrier_label_postlogistics/postlogistics/__init__.py 1970-01-01 00:00:00 +0000
+++ delivery_carrier_label_postlogistics/postlogistics/__init__.py 2013-11-27 09:43:32 +0000
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Yannick Vaucher
+# Copyright 2013 Camptocamp SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from . import web_service
=== added file 'delivery_carrier_label_postlogistics/postlogistics/web_service.py'
--- delivery_carrier_label_postlogistics/postlogistics/web_service.py 1970-01-01 00:00:00 +0000
+++ delivery_carrier_label_postlogistics/postlogistics/web_service.py 2013-11-27 09:43:32 +0000
@@ -0,0 +1,358 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Yannick Vaucher
+# Copyright 2013 Camptocamp SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+import re
+from suds.client import Client, WebFault
+from suds.transport.http import HttpAuthenticated
+from PIL import Image
+from StringIO import StringIO
+
+from openerp.osv import orm
+from openerp.tools.translate import _
+
+_compile_itemid = re.compile('[^0-9A-Za-z+\-_]')
+
+
+class PostlogisticsWebService(object):
+ """ Connector with PostLogistics for labels using post.ch Web Services
+
+ Handbook available here: http://www.poste.ch/post-barcode-cug.htm
+
+ Allows to generate labels
+
+ """
+
+ def __init__(self, company):
+ self.init_connection(company)
+
+ def init_connection(self, company):
+ t = HttpAuthenticated(
+ username=company.postlogistics_username,
+ password=company.postlogistics_password)
+ self.client = Client(
+ company.postlogistics_wsdl_url,
+ transport=t)
+
+ def _send_request(self, request, **kwargs):
+ """ Wrapper for API requests
+
+ :param request: callback for API request
+ :param **kwargs: params forwarded to the callback
+
+ """
+ res = {}
+ try:
+ res['value'] = request(**kwargs)
+ res['success'] = True
+ except WebFault, e:
+ res['success'] = False
+ res['errors'] = [e[0]]
+ except Exception, e:
+ # if authentification error
+ if isinstance(e[0], tuple) and e[0][0] == 401:
+ raise orm.except_orm(
+ _('Error 401'),
+ _('Authorization Required\n\n'
+ 'Please verify postlogistics username and password in:\n'
+ 'Configuration -> Postlogistics'))
+ raise e
+ return res
+
+ def _get_language(self, lang):
+ """ Return a language to iso format from openerp format.
+
+ `iso_code` field in res.lang is not mandatory thus not always set.
+ Use partner language if available, otherwise use english
+
+ :param partner: partner browse record
+ :return: language code to use.
+
+ """
+ available_languages = self.client.factory.create('ns0:Language')
+ lang_code = lang.split('_')[0]
+ if lang_code in available_languages:
+ return lang_code
+ return 'en'
+
+ def read_allowed_services_by_franking_license(self, license, company, lang=None):
+ """ Get a list of allowed service for a postlogistics licence """
+ if not lang:
+ lang = company.partner_id.lang
+ lang = self._get_language(lang)
+ request = self.client.service.ReadAllowedServicesByFrankingLicense
+ return self._send_request(request, License=license, Language=lang)
+
+ def read_service_groups(self, company, lang):
+ """ Get group of services """
+ if not lang:
+ lang = company.partner_id.lang
+ lang = self._get_language(lang)
+ request = self.client.service.ReadServiceGroups
+ return self._send_request(request, Language=lang)
+
+ def read_basic_services(self, company, service_group_id, lang):
+ """ Get basic services for a given service group """
+ if not lang:
+ lang = company.partner_id.lang
+ lang = self._get_language(lang)
+ request = self.client.service.ReadBasicServices
+ return self._send_request(request, Language=lang, ServiceGroupID=service_group_id)
+
+ def read_additional_services(self, company, service_code, lang):
+ """ Get additional services compatible with a basic services """
+ if not lang:
+ lang = company.partner_id.lang
+ lang = self._get_language(lang)
+ request = self.client.service.ReadAdditionalServices
+ return self._send_request(request, Language=lang, PRZL=service_code)
+
+ def read_delivery_instructions(self, company, service_code, lang):
+ """ Get delivery instruction 'ZAW' compatible with a base service """
+ if not lang:
+ lang = company.partner_id.lang
+ lang = self._get_language(lang)
+ request = self.client.service.ReadDeliveryInstructions
+ return self._send_request(request, Language=lang, PRZL=service_code)
+
+ def _prepare_recipient(self, picking):
+ """ Create a ns0:Recipient as a dict from a partner
+
+ :param partner: partner browse record
+ :return a dict containing data for ns0:Recipient
+
+ """
+ partner = picking.partner_id
+
+ recipient = {
+ 'Name1': partner.name,
+ 'Street': partner.street,
+ 'ZIP': partner.zip,
+ 'City': partner.city,
+ 'Country': partner.country_id.code,
+ 'EMail': partner.email or None,
+ }
+
+ if partner.parent_id:
+ recipient['Name2'] = partner.parent_id.name
+ recipient['PersonallyAddressed'] = False
+
+ # Phone and / or mobile should only be diplayed if instruction to
+ # Notify delivery by telephone is set
+ is_phone_required = [option for option in picking.option_ids
+ if option.code == 'ZAW3213']
+ if is_phone_required:
+ if partner.phone:
+ recipient['Phone'] = partner.phone
+
+ if partner.mobile:
+ recipient['Mobile'] = partner.mobile
+
+ # XXX
+ #if partner.POBox
+ #customer['POBox'] = partner.email
+
+ return recipient
+
+ def _prepare_customer(self, picking):
+ """ Create a ns0:Customer as a dict from picking
+
+ This is the Postlogistic Customer, thus the sender
+
+ :param picking: picking browse record
+ :return a dict containing data for ns0:Customer
+
+ """
+ company = picking.company_id
+ partner = company.partner_id
+
+ customer = {
+ 'Name1': partner.name,
+ 'Street': partner.street,
+ 'ZIP': partner.zip,
+ 'City': partner.city,
+ 'Country': partner.country_id.code,
+ 'DomicilePostOffice': company.postlogistics_office,
+ }
+ logo_format = None
+ logo = company.postlogistics_logo
+ if logo:
+ logo_image = Image.open(StringIO(logo.decode('base64')))
+ logo_format = logo_image.format
+ customer['Logo'] = logo
+ customer['LogoFormat'] = logo_format
+ return customer
+
+ def _get_single_option(self, picking, option):
+ option = [opt.code for opt in picking.option_ids
+ if opt.postlogistics_type == option]
+ assert len(option) <= 1
+ return option and option[0]
+
+ def _get_label_layout(self, picking):
+ return self._get_single_option(picking, 'label_layout')
+
+ def _get_output_format(self, picking):
+ return self._get_single_option(picking, 'output_format')
+
+ def _get_image_resolution(self, picking):
+ return self._get_single_option(picking, 'resolution')
+
+ def _get_license(self, picking):
+ """ Get the right license depending on weight """
+ company = picking.company_id
+ #XXX get weight or set it as an option on picking
+ weight = 0
+ if weight > 1.0:
+ return company.postlogistics_license_more_1kg
+ return company.postlogistics_license_less_1kg
+
+ def _prepare_attributes(self, picking):
+ services = [option.code.split(',') for option in picking.option_ids
+ if option.tmpl_option_id.postlogistics_type
+ in ('basic', 'additional', 'delivery')]
+
+ attributes = {
+ 'PRZL': services,
+ }
+ return attributes
+
+ def _get_itemid(self, picking, pack_no):
+ """ Allowed characters are alphanumeric plus `+`, `-` and `_`
+ Last `+` separates picking name and package number
+
+ :return string: itemid
+
+ """
+ name = _compile_itemid.sub('', picking.name)
+ return name + '+' + str(pack_no)
+
+ def _prepare_item_list(self, picking, recipient, attributes):
+ """ Return a list of item made from the pickings """
+ item_list = []
+ for pack_no in range(picking.number_of_packages or 1):
+ item_id = self._get_itemid(picking, pack_no)
+ item = {
+ 'ItemID': item_id,
+ 'Recipient': recipient,
+ 'Attributes': attributes,
+ }
+
+ item_list.append(item)
+
+ return item_list
+
+ def _prepare_data(self, item_list):
+ sending = {
+ 'Item': item_list,
+ }
+ provider = {
+ 'Sending': sending
+ }
+ data = {
+ 'Provider': provider,
+ }
+ return data
+
+ def _prepare_envelope(self, picking, post_customer, data):
+ """ Define envelope for label request """
+ label_layout = self._get_label_layout(picking)
+ output_format = self._get_output_format(picking)
+ image_resolution = self._get_image_resolution(picking)
+
+ label_definitions = {
+ 'LabelLayout': label_layout,
+ 'PrintAddresses': 'RecipientAndCustomer',
+ 'ImageFileType': output_format,
+ 'ImageResolution': image_resolution, #XXX
+ 'PrintPreview': False,
+ }
+ license = self._get_license(picking)
+ file_infos = {
+ 'FrankingLicense': license,
+ 'PpFranking': False,
+ 'CustomerSystem': 'OpenERP',
+ 'Customer': post_customer,
+ }
+
+ envelope = {
+ 'LabelDefinition': label_definitions,
+ 'FileInfos': file_infos,
+ 'Data': data,
+ }
+ return envelope
+
+ def generate_label(self, picking, user_lang='en_US'):
+ """ Generate a label for a picking
+
+ :param picking: picking browse record
+ :param lang: OpenERP language code
+ :return: {
+ value: [{item_id: pack id
+ binary: file returned by API
+ tracking_number: id number for tracking
+ }
+ ]
+ errors: list of error message if any
+ warnings: list of warning message if any
+ }
+
+ """
+ # get options
+ lang = self._get_language(user_lang)
+ post_customer = self._prepare_customer(picking)
+
+ attributes = self._prepare_attributes(picking)
+
+ recipient = self._prepare_recipient(picking)
+ item_list = self._prepare_item_list(picking, recipient, attributes)
+ data = self._prepare_data(item_list)
+
+ envelope = self._prepare_envelope(picking, post_customer, data)
+
+ res = {'value': []}
+ request = self.client.service.GenerateLabel
+ response = self._send_request(request, Language=lang, Envelope=envelope)
+
+ if not response['success']:
+ return response
+ error_messages = []
+ warning_messages = []
+ for item in response['value'].Data.Provider.Sending.Item:
+ if hasattr(item, 'Errors') and item.Errors:
+ for error in item.Errors.Error:
+ message = '[%s] %s' % (error.Code, error.Message)
+ error_messages.append(message)
+ else:
+ res['value'].append({
+ 'item_id': item.ItemID,
+ 'binary': item.Label,
+ 'tracking_number': item.IdentCode,
+ })
+
+ if hasattr(item, 'Warnings') and item.Warnings:
+ for warning in item.Warnings:
+ message = '[%s] %s' % (warning.Code, warning.Message)
+ warning_messages.append(message)
+
+ if error_messages:
+ res['errors'] = error_messages
+ if warning_messages:
+ res['warnings'] = warning_messages
+ return res
=== added file 'delivery_carrier_label_postlogistics/res_config.py'
--- delivery_carrier_label_postlogistics/res_config.py 1970-01-01 00:00:00 +0000
+++ delivery_carrier_label_postlogistics/res_config.py 2013-11-27 09:43:32 +0000
@@ -0,0 +1,403 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Yannick Vaucher
+# Copyright 2013 Camptocamp SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from openerp.osv import orm, fields
+from openerp.tools.translate import _
+
+from postlogistics.web_service import PostlogisticsWebService
+
+
+class PostlogisticsConfigSettings(orm.TransientModel):
+ _name = 'postlogistics.config.settings'
+ _inherit = 'res.config.settings'
+
+ _columns = {
+ 'company_id': fields.many2one('res.company', 'Company', required=True),
+ 'wsdl_url': fields.related(
+ 'company_id', 'postlogistics_wsdl_url',
+ string='WSDL URL', type='char'),
+ 'username': fields.related(
+ 'company_id', 'postlogistics_username',
+ string='Username', type='char'),
+ 'password': fields.related(
+ 'company_id', 'postlogistics_password',
+ string='Password', type='char'),
+ 'license_less_1kg': fields.related(
+ 'company_id', 'postlogistics_license_less_1kg',
+ string='License less than 1kg', type='char'),
+ 'license_more_1kg': fields.related(
+ 'company_id', 'postlogistics_license_more_1kg',
+ string='License more than 1kg', type='char'),
+ 'license_vinolog': fields.related(
+ 'company_id', 'postlogistics_license_vinolog',
+ string='License VinoLog', type='char'),
+ 'logo': fields.related(
+ 'company_id', 'postlogistics_logo',
+ string='Company Logo on Post labels', type='binary',
+ help="Optional company logo to show on label.\n"
+ "If using an image / logo, please note the following:\n"
+ "– Image width: 47 mm\n"
+ "– Image height: 25 mm\n"
+ "– File size: max. 30 kb\n"
+ "– File format: GIF or PNG\n"
+ "– Colour table: indexed colours, max. 200 colours\n"
+ "– The logo will be printed rotated counter-clockwise by 90°\n"
+ "We recommend using a black and white logo for printing in the\n"
+ "ZPL2 format."
+ ),
+ 'office': fields.related(
+ 'company_id', 'postlogistics_office',
+ string='Domicile Post office', type='char',
+ help="Post office which will receive the shipped goods"),
+ #'default_postlogistics_logo_layout': fields.related(
+ #'company_id', 'default_postlogistics_logo_layout',
+ #string='Domicile Post office', type='char',
+ #help="Post office which will receive the shipped goods"),
+ #'default_postlogistics_output_format': fields.related(
+ #'company_id', 'default_postlogistics_logo_layout',
+ #string='Domicile Post office', type='char',
+ #help="Post office which will receive the shipped goods"),
+ #'default_postlogistics_output_format': fields.related(
+ #'company_id', 'default_postlogistics_logo_layout',
+ #string='Domicile Post office', type='char',
+ #help="Post office which will receive the shipped goods"),
+ }
+
+ def _default_company(self, cr, uid, context=None):
+ user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
+ return user.company_id.id
+
+ _defaults = {
+ 'company_id': _default_company,
+ }
+
+ def create(self, cr, uid, values, context=None):
+ id = super(PostlogisticsConfigSettings, self).create(cr, uid, values, context)
+ # Hack: to avoid some nasty bug, related fields are not written
+ # upon record creation. Hence we write on those fields here.
+ vals = {}
+ for fname, field in self._columns.iteritems():
+ if isinstance(field, fields.related) and fname in values:
+ vals[fname] = values[fname]
+ self.write(cr, uid, [id], vals, context)
+ return id
+
+ def onchange_company_id(self, cr, uid, ids, company_id, context=None):
+ # update related fields
+ values = {}
+ values['currency_id'] = False
+ if not company_id:
+ return {'value': values}
+ company = self.pool.get('res.company').browse(cr, uid, company_id, context=context)
+ values = {
+ 'username': company.postlogistics_username,
+ 'password': company.postlogistics_password,
+ 'license_less_1kg': company.postlogistics_license_less_1kg,
+ 'license_more_1kg': company.postlogistics_license_more_1kg,
+ 'license_vinolog': company.postlogistics_license_vinolog,
+ 'logo': company.postlogistics_logo,
+ 'office': company.postlogistics_office,
+ }
+ return {'value': values}
+
+ def _get_delivery_instructions(self, cr, uid, ids, web_service,
+ company, service_code, context=None):
+ if context is None:
+ context = {}
+
+ lang = context.get('lang', 'en')
+ service_code_list = service_code.split(',')
+ res = web_service.read_delivery_instructions(company, service_code_list, lang)
+ if 'errors' in res:
+ errors = '\n'.join(res['errors'])
+ error_message = (_('Could not retrieve Postlogistics delivery'
+ 'instructions:\n%s') % errors)
+ raise orm.except_orm(_('Error'), error_message)
+
+ if not res['value']:
+ return {}
+
+ if hasattr(res['value'], 'Errors') and res['value'].Errors:
+ for error in res['value'].Errors.Error:
+ message = '[%s] %s' % (error.Code, error.Message)
+ raise orm.except_orm('Error', message)
+
+ delivery_instructions = {}
+ for service in res['value'].DeliveryInstructions:
+ service_code = service.PRZL
+ delivery_instructions[service_code] = {'name': service.Description}
+
+ return delivery_instructions
+
+ def _update_delivery_instructions(self, cr, uid, ids, web_service,
+ additional_services, context=None):
+ if context is None:
+ context = {}
+ ir_model_data_obj = self.pool.get('ir.model.data')
+ carrier_option_obj = self.pool.get('delivery.carrier.template.option')
+
+ xmlid = 'delivery_carrier_label_laposte', 'postlogistics'
+ postlogistics_partner = ir_model_data_obj.get_object(
+ cr, uid, *xmlid, context=context)
+
+ for service_code, data in additional_services.iteritems():
+
+ option_ids = carrier_option_obj.search(
+ cr, uid,
+ [('code', '=', service_code),
+ ('postlogistics_type', '=', 'delivery')
+ ],
+ context=context)
+
+ if option_ids:
+ carrier_option_obj.write(cr, uid, option_ids, data, context=context)
+ else:
+ data.update(code=service_code,
+ postlogistics_type='delivery',
+ partner_id=postlogistics_partner.id)
+ carrier_option_obj.create(cr, uid, data, context=context)
+
+ def _get_additional_services(self, cr, uid, ids, web_service,
+ company, service_code, context=None):
+ if context is None:
+ context = {}
+
+ lang = context.get('lang', 'en')
+ service_code_list = service_code.split(',')
+ res = web_service.read_additional_services(company, service_code_list, lang)
+ if 'errors' in res:
+ errors = '\n'.join(res['errors'])
+ error_message = (_('Could not retrieve Postlogistics base '
+ 'services:\n%s') % errors)
+ raise orm.except_orm(_('Error'), error_message)
+
+ if not res['value']:
+ return {}
+
+ if hasattr(res['value'], 'Errors') and res['value'].Errors:
+ for error in res['value'].Errors.Error:
+ message = '[%s] %s' % (error.Code, error.Message)
+ raise orm.except_orm('Error', message)
+
+ additional_services = {}
+ for service in res['value'].AdditionalService:
+ service_code = service.PRZL
+ additional_services[service_code] = {'name': service.Description}
+
+ return additional_services
+
+ def _update_additional_services(self, cr, uid, ids, web_service,
+ additional_services, context=None):
+ if context is None:
+ context = {}
+ ir_model_data_obj = self.pool.get('ir.model.data')
+ carrier_option_obj = self.pool.get('delivery.carrier.template.option')
+
+ postlogistics_partner = ir_model_data_obj.get_object(
+ cr, uid, 'delivery_carrier_label_laposte', 'postlogistics', context=context)
+
+ for service_code, data in additional_services.iteritems():
+
+ option_ids = carrier_option_obj.search(cr, uid, [
+ ('code', '=', service_code),
+ ('postlogistics_type', '=', 'additional')
+ ], context=context)
+
+ if option_ids:
+ carrier_option_obj.write(cr, uid, option_ids, data, context=context)
+ else:
+ data.update(code=service_code,
+ postlogistics_type='additional',
+ partner_id=postlogistics_partner.id)
+ carrier_option_obj.create(cr, uid, data, context=context)
+
+ def _update_basic_services(self, cr, uid, ids, web_service, company, group_id, context=None):
+ """ Update of basic services
+
+ A basic service can be part only of one service group
+
+ :return: {additional_services: {<service_code>: service_data}
+ delivery_instructions: {<service_code>: service_data}
+ }
+
+ """
+ if context is None:
+ context = {}
+ ir_model_data_obj = self.pool.get('ir.model.data')
+ service_group_obj = self.pool.get('postlogistics.service.group')
+ carrier_option_obj = self.pool.get('delivery.carrier.template.option')
+
+ xmlid = 'delivery_carrier_label_laposte', 'postlogistics'
+ postlogistics_partner = ir_model_data_obj.get_object(
+ cr, uid, *xmlid, context=context)
+ lang = context.get('lang', 'en')
+
+ group = service_group_obj.browse(cr, uid, group_id, context=context)
+
+ res = web_service.read_basic_services(company, group.group_extid, lang)
+ if 'errors' in res:
+ errors = '\n'.join(res['errors'])
+ error_message = (_('Could not retrieve Postlogistics base '
+ 'services:\n%s') % errors)
+ raise orm.except_orm(_('Error'), error_message)
+
+ additional_services = {}
+ delivery_instructions = {}
+ # Create or update basic service
+ for service in res['value'].BasicService:
+ service_code = ','.join(service.PRZL)
+ option_ids = carrier_option_obj.search(cr, uid, [
+ ('code', '=', service_code),
+ ('postlogistics_service_group_id', '=', group_id),
+ ('postlogistics_type', '=', 'basic')
+ ], context=context)
+ data = {'name': service.Description}
+ if option_ids:
+ carrier_option_obj.write(cr, uid, option_ids, data, context=context)
+ option_id = option_ids[0]
+ else:
+ data.update(code=service_code,
+ postlogistics_service_group_id=group_id,
+ partner_id=postlogistics_partner.id,
+ postlogistics_type='basic')
+ option_id = carrier_option_obj.create(cr, uid, data, context=context)
+
+ # Get related services
+ allowed_services = self._get_additional_services(
+ cr, uid, ids, web_service, company, service_code, context=context)
+ for key, value in additional_services.iteritems():
+ if key in allowed_services:
+ additional_services[key]['postlogistics_basic_service_ids'][0][2].append(option_id)
+ del allowed_services[key]
+ for key, value in allowed_services.iteritems():
+ additional_services[key] = value
+ additional_services[key]['postlogistics_basic_service_ids'] = [(6, 0, [option_id])]
+
+ allowed_services = self._get_delivery_instructions(
+ cr, uid, ids, web_service, company, service_code, context=context)
+ for key, value in delivery_instructions.iteritems():
+ if key in allowed_services:
+ delivery_instructions[key]['postlogistics_basic_service_ids'][0][2].append(option_id)
+ del allowed_services[key]
+ for key, value in allowed_services.iteritems():
+ delivery_instructions[key] = value
+ delivery_instructions[key]['postlogistics_basic_service_ids'] = [(6, 0, [option_id])]
+
+ return {'additional_services': additional_services,
+ 'delivery_instructions': delivery_instructions}
+
+ def _update_service_groups(self, cr, uid, ids, web_service, company, context=None):
+ """ Also updates additional services and delivery instructions
+ as they are shared between groups
+
+ """
+ if context is None:
+ context = {}
+ service_group_obj = self.pool.get('postlogistics.service.group')
+
+ lang = context.get('lang', 'en')
+
+ res = web_service.read_service_groups(company, lang)
+ if 'errors' in res:
+ errors = '\n'.join(res['errors'])
+ error_message = (_('Could not retrieve Postlogistics group '
+ 'services:\n%s') % errors)
+ raise orm.except_orm(_('Error'), error_message)
+
+ additional_services = {}
+ delivery_instructions = {}
+
+ # Create or update groups
+ for group in res['value'].ServiceGroup:
+ group_extid = group.ServiceGroupID
+ group_ids = service_group_obj.search(
+ cr, uid, [('group_extid', '=', group_extid)], context=context)
+ data = {'name': group.Description}
+ if group_ids:
+ service_group_obj.write(cr, uid, group_ids, data, context=context)
+ group_id = group_ids[0]
+ else:
+ data['group_extid'] = group_extid
+ group_id = service_group_obj.create(cr, uid, data, context=context)
+
+ # Get related services for all basic services of this group
+ res = self._update_basic_services(cr, uid, ids, web_service,
+ company, group_id, context=context)
+
+ allowed_services = res.get('additional_services', {})
+ for key, value in additional_services.iteritems():
+ if key in allowed_services:
+ option_ids = allowed_services[key]['postlogistics_basic_service_ids'][0][2]
+ additional_services[key]['postlogistics_basic_service_ids'][0][2].extend(option_ids)
+ del allowed_services[key]
+ additional_services.update(allowed_services)
+
+ allowed_services = res.get('delivery_instructions', {})
+ for key, value in delivery_instructions.iteritems():
+ if key in allowed_services:
+ option_ids = allowed_services[key]['postlogistics_basic_service_ids'][0][2]
+ delivery_instructions[key]['postlogistics_basic_service_ids'][0][2].extend(option_ids)
+ del allowed_services[key]
+ delivery_instructions.update(allowed_services)
+
+ # Update related services
+ self._update_additional_services(cr, uid, ids, web_service,
+ additional_services, context=context)
+ self._update_delivery_instructions(cr, uid, ids, web_service,
+ delivery_instructions, context=context)
+
+ def update_postlogistics_options(self, cr, uid, ids, context=None):
+ """ This action will update all postlogistics option by
+ importing services from PostLogistics WebService API
+
+ The object we create are 'delivey.carrier.template.option'
+
+ """
+ if context is None:
+ context = {}
+ user_obj = self.pool.get('res.users')
+
+ company = user_obj.browse(cr, uid, uid, context=context).company_id
+
+ web_service = PostlogisticsWebService(company)
+
+ # make sure we create source text in en_US
+ ctx = context.copy()
+ ctx['lang'] = 'en_US'
+ self._update_service_groups(cr, uid, ids, web_service, company, context=ctx)
+
+ language_obj = self.pool.get('res.lang')
+ language_ids = language_obj.search(cr, uid, [], context=context)
+
+ languages = language_obj.browse(cr, uid, language_ids, context=context)
+
+ # handle translations
+ # we call the same methode with a different language context
+ for lang_br in languages:
+ lang = lang_br.code
+ ctx = context.copy()
+ ctx['lang'] = lang_br.code
+ postlogistics_lang = web_service._get_language(lang)
+ # add translations only for languages that exists on postlogistics
+ # english source will be kept for other languages
+ if postlogistics_lang == 'en':
+ continue
+ self._update_service_groups(cr, uid, ids, web_service, company, context=ctx)
+ return True
=== added file 'delivery_carrier_label_postlogistics/res_config_view.xml'
--- delivery_carrier_label_postlogistics/res_config_view.xml 1970-01-01 00:00:00 +0000
+++ delivery_carrier_label_postlogistics/res_config_view.xml 2013-11-27 09:43:32 +0000
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+
+ <record id="view_postlogistics_config_settings" model="ir.ui.view">
+ <field name="name">postlogistics settings</field>
+ <field name="model">postlogistics.config.settings</field>
+ <field name="arch" type="xml">
+ <form string="Configure Postlogistics" version="7.0" class="oe_form_configuration">
+ <header>
+ <button string="Apply" type="object" name="execute" class="oe_highlight"/>
+ or
+ <button string="Cancel" type="object" name="cancel" class="oe_link"/>
+ </header>
+
+ <group groups="base.group_multi_company">
+ <div>
+ <div>
+ <label for="company_id" string="Select Company"/>
+ <field name="company_id"
+ widget="selection"
+ on_change="onchange_company_id(company_id, context)"
+ class="oe_inline"/>
+ </div>
+ </div>
+ </group>
+ <separator string="Web Service Authentification"/>
+ <group>
+ <div>
+ <div>
+ <label for="username"/>
+ <field name="username" class="oe_inline"/>
+ </div>
+ <div>
+ <label for="password"/>
+ <field name="password" class="oe_inline"/>
+ </div>
+ </div>
+ </group>
+ <separator string="Licenses"/>
+ <group>
+ <div>
+ <div>
+ <label for="license_less_1kg"/>
+ <field name="license_less_1kg" class="oe_inline"/>
+ </div>
+ <div>
+ <label for="license_more_1kg"/>
+ <field name="license_more_1kg" class="oe_inline"/>
+ </div>
+ <div>
+ <label for="license_vinolog"/>
+ <field name="license_vinolog" class="oe_inline"/>
+ </div>
+ </div>
+ </group>
+ <separator string="Sender Informations"/>
+ <group>
+ <div>
+ <div>
+ <label for="logo"/>
+ <field name="logo" widget="image"/>
+ </div>
+ <div>
+ <label for="office"/>
+ <field name="office" class="oe_inline"/>
+ </div>
+ </div>
+ </group>
+ <group>
+ <div>
+ <div>
+ <button string="Update PostLogistics Services" type="object" name="update_postlogistics_options" class="oe_highlight"/>
+ </div>
+ </div>
+ </group>
+ </form>
+ </field>
+ </record>
+
+ <record id="action_postlogistics_config" model="ir.actions.act_window">
+ <field name="name">Configure Postlogistics</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">postlogistics.config.settings</field>
+ <field name="view_mode">form</field>
+ <field name="target">inline</field>
+ </record>
+
+ <menuitem id="menu_postlogistics_config" name="Postlogistics" parent="base.menu_config"
+ sequence="20" action="action_postlogistics_config"/>
+
+ </data>
+</openerp>
=== added file 'delivery_carrier_label_postlogistics/res_partner_data.xml'
--- delivery_carrier_label_postlogistics/res_partner_data.xml 1970-01-01 00:00:00 +0000
+++ delivery_carrier_label_postlogistics/res_partner_data.xml 2013-11-27 09:43:32 +0000
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data noupdate="1">
+ <record id="postlogistics" model="res.partner">
+ <field name="image">/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsK
+CwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQU
+FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCABkAMMDASIA
+AhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA
+AAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3
+ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm
+p6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA
+AwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx
+BhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK
+U1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3
+uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD69ooo
+r/No/YAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA
+5b4p+NW+Gvw38ReKRafbm0m0a6+yvLt83b/Du/hr5B0v/gp7CbmH+1fhzPb6ez7WuLTUN7f8B3Kq
+t/31X0r+1ASf2dfiN7aLPzXzR8Mb3wqn/BO3VY/EUun/AHNR+yxXDJ5v2rzW8ryv4t2/bX7Nwrle
+U18q+s47De2lKtGn7rkuVSXkfP42rWjX5KcuX3eY+zPA/jbSPiR4T0zxLoN39s0nUYvNgl27X/2k
+Zf4WVvlre9sc18AfAr4+yfs6/sZw6vNbLf6rqOuXUGi2lx91vkXc7f7CNu/4FU1n+1P8ffg/qWhe
+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
+/9k=</field>
+ <field name="name">PostLogistics</field>
+ <field name="customer" eval="False"/>
+ <field name="supplier" eval="False"/>
+ <field name="email">webservice@xxxxxxx</field>
+ </record>
+ </data>
+</openerp>
=== added file 'delivery_carrier_label_postlogistics/stock.py'
--- delivery_carrier_label_postlogistics/stock.py 1970-01-01 00:00:00 +0000
+++ delivery_carrier_label_postlogistics/stock.py 2013-11-27 09:43:32 +0000
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Yannick Vaucher
+# Copyright 2013 Camptocamp SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from openerp.osv import orm
+
+from postlogistics.web_service import PostlogisticsWebService
+
+
+class stock_picking_out(orm.Model):
+ _inherit = 'stock.picking.out'
+
+ def _generate_poste_ch_label(self, cr, uid, picking, context=None):
+ user_obj = self.pool.get('res.users')
+ user = user_obj.browse(cr, uid, uid, context=context)
+ company = user.company_id
+ web_service = PostlogisticsWebService(company)
+ res = web_service.generate_label(picking, user.lang)
+
+ if 'errors' in res:
+ raise orm.except_orm('Error', '\n'.join(res['errors']))
+ # XXX What with multiple pack for one picking ?
+ tracking_number = res['value'][0]['tracking_number']
+ # write tracking number on picking XXX multi ?
+ self.write(cr, uid, picking.id,
+ {'carrier_tracking_ref': tracking_number},
+ context=context)
+ return res['value'][0]['binary'].decode('base64')
+
+ def generate_single_label(self, cr, uid, ids, context=None):
+ """ Add label generation for Postlogistics """
+ if isinstance(ids, (long, int)):
+ ids = [ids]
+ assert len(ids) == 1
+ picking = self.browse(cr, uid, ids[0], context=context)
+ if picking.carrier_id.type == 'postlogistics':
+ return self._generate_poste_ch_label(cr, uid, picking, context=context)
+ return super(stock_picking_out, self).generate_single_label(cr, uid, ids, context=None)
References