You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

211 lines
11 KiB

# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Ayana kp(odoo@cybrosys.com)
#
# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1)
# It is forbidden to publish, distribute, sublicense, or sell copies of the
# Software or modified copies of the Software.
#
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
###############################################################################
import logging
from markupsafe import Markup
from zeep.helpers import serialize_object
from odoo import models, _
from odoo.exceptions import UserError
from odoo.tools import pdf
from odoo.addons.delivery_fedex.models.fedex_request import FedexRequest, \
_convert_curr_iso_fdx
_logger = logging.getLogger(__name__)
class DeliveryCarrier(models.Model):
"""This class inherits from the base delivery carrier model and
allows for additional customization and functionality to be added
to delivery carriers. """
_inherit = "delivery.carrier"
def fedex_send_shipping(self, picking):
"""Overriding default fedex integration function to
check with our condition"""
if picking.batch_id and not picking.carrier_tracking_ref:
partner_id = picking.partner_id.id
carrier_id = picking.carrier_id.id
filtered_picking_ids = picking.batch_id.picking_ids.filtered(
lambda
x: x.partner_id.id == partner_id and x.carrier_id.id == carrier_id)
# Now you have filtered_picking_ids with the desired records
if len(filtered_picking_ids) > 1:
response = self._batch_fedex_send_shipping(picking,
filtered_picking_ids)
return response
else:
res = super().fedex_send_shipping(picking)
return res
else:
res = super().fedex_send_shipping(picking)
return res
def _batch_fedex_send_shipping(self, picking, filtered_picking_ids):
""" Function for batch transfers picking to connect fedex and return
same tracking numbers for all picking with same
carrier id and customer. """
res = []
order_currency = picking.sale_id.currency_id or picking.company_id.currency_id
srm = FedexRequest(self.log_xml, request_type="shipping",
prod_environment=self.prod_environment)
superself = self.sudo()
srm.web_authentication_detail(superself.fedex_developer_key,
superself.fedex_developer_password)
srm.client_detail(superself.fedex_account_number,
superself.fedex_meter_number)
srm.transaction_detail(picking.id)
package_type = picking.package_ids and picking.package_ids[
0].package_type_id.shipper_package_code or self.fedex_default_package_type_id.shipper_package_code
srm.shipment_request(self.fedex_droppoff_type, self.fedex_service_type,
package_type, self.fedex_weight_unit,
self.fedex_saturday_delivery)
srm.set_currency(_convert_curr_iso_fdx(order_currency.name))
srm.set_shipper(picking.company_id.partner_id,
picking.picking_type_id.warehouse_id.partner_id)
srm.set_recipient(picking.partner_id)
srm.shipping_charges_payment(superself.fedex_account_number)
srm.shipment_label('COMMON2D', self.fedex_label_file_type,
self.fedex_label_stock_type,
'TOP_EDGE_OF_TEXT_FIRST', 'SHIPPING_LABEL_FIRST')
order = picking.sale_id
net_weight = 0.0
if 'INTERNATIONAL' in self.fedex_service_type or self.fedex_service_type == 'FEDEX_REGIONAL_ECONOMY' or (
picking.partner_id.country_id.code == 'IN' and picking.picking_type_id.warehouse_id.partner_id.country_id.code == 'IN'):
commodities = self._get_commodities_from_stock_move_lines(
picking.move_line_ids)
for commodity in commodities:
srm.commodities(self, commodity,
_convert_curr_iso_fdx(order_currency.name))
total_commodities_amount = sum(
c.monetary_value * c.qty for c in commodities)
srm.customs_value(_convert_curr_iso_fdx(order_currency.name),
total_commodities_amount, "NON_DOCUMENTS")
srm.duties_payment(order.warehouse_id.partner_id,
superself.fedex_account_number,
superself.fedex_duty_payment)
send_etd = superself.env['ir.config_parameter'].get_param(
"delivery_fedex.send_etd")
srm.commercial_invoice(self.fedex_document_stock_type, send_etd)
package_count = 1
packages = []
package_ids = []
for pick in filtered_picking_ids:
if not pick.carrier_tracking_ref:
if pick.package_ids not in package_ids:
package_ids.append(pick.package_ids)
converted_weight = self._fedex_convert_weight(
pick.shipping_weight, self.fedex_weight_unit)
package_count += len(pick.package_ids)
package = self._get_packages_from_picking(pick,
self.fedex_default_package_type_id)
packages.append(package)
if isinstance(converted_weight, (int, float)):
net_weight += converted_weight
po_number = order.display_name or False
dept_number = False
if picking.partner_id.country_id.code == 'IN' and picking.picking_type_id.warehouse_id.partner_id.country_id.code == 'IN':
po_number = 'B2B' if picking.partner_id.commercial_partner_id.is_company else 'B2C'
dept_number = 'BILL D/T: SENDER'
master_tracking_id = False
package_labels = []
carrier_tracking_refs = []
flattened_packages = [item for sublist in packages for item in sublist]
for sequence, package in enumerate(flattened_packages, start=1):
srm.add_package(
self,
package,
_convert_curr_iso_fdx(package.company_id.currency_id.name),
sequence_number=sequence,
po_number=po_number,
dept_number=dept_number,
reference=picking.display_name,
)
srm.set_master_package(net_weight, len(flattened_packages),
master_tracking_id=master_tracking_id)
self._fedex_update_srm(srm, 'ship', picking=picking)
request = serialize_object(
dict(WebAuthenticationDetail=srm.WebAuthenticationDetail,
ClientDetail=srm.ClientDetail,
TransactionDetail=srm.TransactionDetail,
VersionId=srm.VersionId,
RequestedShipment=srm.RequestedShipment))
self._fedex_add_extra_data_to_request(request, 'ship')
response = srm.process_shipment(request)
warnings = response.get('warnings_message')
if warnings:
_logger.info(warnings)
if response.get('errors_message'):
raise UserError(response['errors_message'])
package_name = package.name or 'package-' + str(sequence)
package_labels.append((package_name, srm.get_label()))
carrier_tracking_refs.append(response['tracking_number'])
if sequence == 1:
master_tracking_id = response['master_tracking_id']
# Last package
if sequence == len(flattened_packages):
carrier_price = self._get_request_price(response['price'],
order,
order_currency)
if self.fedex_label_file_type != 'PDF':
attachments = [('%s-%s.%s' % (
self._get_delivery_label_prefix(), pl[0],
self.fedex_label_file_type), pl[1]) for pl in
package_labels]
if self.fedex_label_file_type == 'PDF':
attachments = [
('%s.pdf' % (self._get_delivery_label_prefix()),
pdf.merge_pdf(
[pl[1] for pl in package_labels]))]
num = 0
for pick in filtered_picking_ids:
if not pick.carrier_tracking_ref and num < len(
carrier_tracking_refs):
logmessage = Markup(
_("Shipment created into Fedex<br/>"
"<b>Tracking Numbers:</b> %s<br/>"
"<b>Packages:</b> %s")) % (
carrier_tracking_refs[num],
pick.package_ids.name)
num += 1
pick.message_post(body=logmessage,
attachments=attachments)
shipping_data = {'exact_price': carrier_price,
'tracking_number': ','.join(
carrier_tracking_refs)}
res = res + [shipping_data]
logmessage = Markup(_("Shipment created into Fedex<br/>"
"<b>Tracking Numbers:</b> %s<br/>"
"<b>Packages:</b> %s")) % (
','.join(carrier_tracking_refs),
','.join([pl[0] for pl in package_labels]))
if self.fedex_label_file_type != 'PDF':
attachments = [('%s-%s.%s' % (
self._get_delivery_label_prefix(), pl[0],
self.fedex_label_file_type), pl[1]) for pl in
package_labels]
if self.fedex_label_file_type == 'PDF':
attachments = [('%s.pdf' % (
self._get_delivery_label_prefix()), pdf.merge_pdf(
[pl[1] for pl in package_labels]))]
picking.batch_id.message_post(body=logmessage,
attachments=attachments)
return res