188 lines
6.8 KiB
Python
Executable File
188 lines
6.8 KiB
Python
Executable File
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
|
# this repository contains the full copyright notices and license terms.
|
|
from itertools import zip_longest
|
|
|
|
from trytond.i18n import gettext
|
|
from trytond.model import fields
|
|
from trytond.model.exceptions import AccessError
|
|
from trytond.pool import Pool, PoolMeta
|
|
from trytond.transaction import Transaction
|
|
from trytond.wizard import StateAction, StateTransition, Wizard
|
|
|
|
|
|
class Package(metaclass=PoolMeta):
|
|
__name__ = 'stock.package'
|
|
|
|
sendcloud_shipping_id = fields.Integer("ID", readonly=True)
|
|
sendcloud_shipping_tracking_url = fields.Char(
|
|
"Tracking URL", readonly=True)
|
|
|
|
def get_shipping_tracking_url(self, name):
|
|
url = super().get_shipping_tracking_url(name)
|
|
if (self.shipping_reference
|
|
and self.shipment
|
|
and self.shipment.id >= 0
|
|
and self.shipment.carrier
|
|
and self.shipment.carrier.shipping_service == 'sendcloud'):
|
|
url = self.sendcloud_shipping_tracking_url
|
|
return url
|
|
|
|
@classmethod
|
|
def copy(cls, packages, default=None):
|
|
if default is None:
|
|
default = {}
|
|
else:
|
|
default = default.copy()
|
|
default.setdefault('sendcloud_shipping_id')
|
|
default.setdefault('sendcloud_shipping_tracking_url')
|
|
return super().copy(packages, default=default)
|
|
|
|
|
|
class ShippingSendcloudMixin:
|
|
__slots__ = ()
|
|
|
|
def get_sendcloud_credential(self):
|
|
pool = Pool()
|
|
SendcloudCredential = pool.get('carrier.credential.sendcloud')
|
|
|
|
pattern = self._get_sendcloud_credential_pattern()
|
|
for credential in SendcloudCredential.search([]):
|
|
if credential.match(pattern):
|
|
return credential
|
|
|
|
def _get_sendcloud_credential_pattern(self):
|
|
return {
|
|
'company': self.company.id,
|
|
}
|
|
|
|
def validate_packing_sendcloud(self):
|
|
pass
|
|
|
|
|
|
class ShipmentOut(ShippingSendcloudMixin, metaclass=PoolMeta):
|
|
__name__ = 'stock.shipment.out'
|
|
|
|
|
|
class ShipmentInReturn(ShippingSendcloudMixin, metaclass=PoolMeta):
|
|
__name__ = 'stock.shipment.in.return'
|
|
|
|
|
|
class CreateShipping(metaclass=PoolMeta):
|
|
__name__ = 'stock.shipment.create_shipping'
|
|
|
|
sendcloud = StateAction(
|
|
'stock_package_shipping_sendcloud.act_create_shipping_wizard')
|
|
|
|
def transition_start(self):
|
|
next_state = super().transition_start()
|
|
if self.record.carrier.shipping_service == 'sendcloud':
|
|
next_state = 'sendcloud'
|
|
return next_state
|
|
|
|
def do_sendcloud(self, action):
|
|
ctx = Transaction().context
|
|
return action, {
|
|
'model': ctx['active_model'],
|
|
'id': ctx['active_id'],
|
|
'ids': [ctx['active_id']],
|
|
}
|
|
|
|
|
|
class CreateShippingSendcloud(Wizard):
|
|
"Create Sendcloud Shipping"
|
|
__name__ = 'stock.shipment.create_shipping.sendcloud'
|
|
|
|
start = StateTransition()
|
|
|
|
def transition_start(self):
|
|
pool = Pool()
|
|
Package = pool.get('stock.package')
|
|
|
|
shipment = self.record
|
|
if shipment.shipping_reference:
|
|
raise AccessError(
|
|
gettext('stock_package_shipping_sendcloud'
|
|
'.msg_shipment_has_shipping_reference_number',
|
|
shipment=shipment.rec_name))
|
|
|
|
credential = shipment.get_sendcloud_credential()
|
|
carrier = shipment.carrier
|
|
packages = shipment.root_packages
|
|
|
|
parcels = []
|
|
for package in packages:
|
|
parcels.append(self.get_parcel(shipment, package, credential))
|
|
parcels = credential.create_parcels(parcels)
|
|
|
|
for package, parcel in zip_longest(packages, parcels):
|
|
format_ = shipment.carrier.sendcloud_format.split()
|
|
label_url = parcel['label']
|
|
for key in format_:
|
|
try:
|
|
index = int(key)
|
|
except ValueError:
|
|
key += '_printer'
|
|
label_url = label_url[key]
|
|
else:
|
|
label_url = label_url[index]
|
|
package.sendcloud_shipping_id = parcel['id']
|
|
package.shipping_label = credential.get_label(label_url)
|
|
package.shipping_label_mimetype = carrier.shipping_label_mimetype
|
|
package.shipping_reference = parcel['tracking_number']
|
|
package.sendcloud_shipping_tracking_url = parcel['tracking_url']
|
|
if not shipment.shipping_reference:
|
|
shipment.shipping_reference = (
|
|
parcel.get('colli_tracking_number')
|
|
or parcel['tracking_number'])
|
|
Package.save(packages)
|
|
shipment.save()
|
|
|
|
return 'end'
|
|
|
|
def get_parcel(self, shipment, package, credential, usage=None):
|
|
pool = Pool()
|
|
UoM = pool.get('product.uom')
|
|
ModelData = pool.get('ir.model.data')
|
|
|
|
cm = UoM(ModelData.get_id('product', 'uom_centimeter'))
|
|
kg = UoM(ModelData.get_id('product', 'uom_kilogram'))
|
|
party = shipment.shipping_to
|
|
address = shipment.shipping_to_address
|
|
phone = address.contact_mechanism_get(
|
|
{'phone', 'mobile'}, usage=usage)
|
|
email = address.contact_mechanism_get('email', usage=usage)
|
|
street_lines = (address.street or '').splitlines()
|
|
parcel = {
|
|
'name': address.party_full_name,
|
|
'company_name': (
|
|
party.full_name if party.full_name != address.party_full_name
|
|
else None),
|
|
'address': street_lines[0] if street_lines else '',
|
|
'address_2': (
|
|
' '.join(street_lines[1:]) if len(street_lines) > 1 else ''),
|
|
'city': address.city,
|
|
'postal_code': address.postal_code,
|
|
'country': address.country.code if address.country else None,
|
|
'country_state': (
|
|
address.subdivision.code.split('-', 1)[1]
|
|
if address.subdivision else None),
|
|
'telephone': phone.value if phone else None,
|
|
'email': email.value if email else None,
|
|
'sender_address': credential.get_sender_address(shipment),
|
|
'external_reference': '/'.join([shipment.number, package.number]),
|
|
'quantity': 1,
|
|
'order_number': shipment.number,
|
|
'weight': UoM.compute_qty(
|
|
package.weight_uom, package.total_weight, kg),
|
|
'length': UoM.compute_qty(package.length_uom, package.length, cm),
|
|
'width': UoM.compute_qty(package.width_uom, package.width, cm),
|
|
'height': UoM.compute_qty(package.height_uom, package.height, cm),
|
|
'request_label': True,
|
|
}
|
|
shipping_method = credential.get_shipping_method(shipment)
|
|
if shipping_method:
|
|
parcel['shipment'] = {'id': shipping_method}
|
|
else:
|
|
parcel['apply_shipping_rules'] = True
|
|
return parcel
|