Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LIMS-832]Feature: Use shipping service for incoming shipments #630

Merged
1 change: 1 addition & 0 deletions api/config_sample.php
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@

# Shipping service details
$use_shipping_service = null;
$use_shipping_service_incoming_shipments = null;
$shipping_service_url = null;
$shipping_service_links_in_emails = null;

Expand Down
11 changes: 6 additions & 5 deletions api/src/Database/DatabaseFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,26 @@ function __construct($databaseConnectionFactory)

public function get($databaseType = null)
{
global $dbtype;

if ( $databaseType == null) {
// Global variable is named $dbtype in config.php.
global $dbtype;
$databaseType = $dbtype;
}

if (!$databaseType) {
error_log('Database type variable, dbtype, is not specified in config.php - defaulting to MySql.');
$database_type = 'MySQL';
$databaseType = 'MySQL';
}

// Determine fully-qualified class name of database class corresponding to $database_type.
if (key_exists(strtolower($databaseType), $this->database_types)) {
$dbType = $this->database_types[strtolower($databaseType)];
$selectedDBConfig = $this->database_types[strtolower($databaseType)];

$full_class_name = 'SynchWeb\\Database\\Type\\' . $dbType["dbClassName"];;
$full_class_name = 'SynchWeb\\Database\\Type\\' . $selectedDBConfig["dbClassName"];

if (class_exists($full_class_name)) {
$conn = $this->databaseConnectionFactory->get($dbType["dataConnectionName"]);
$conn = $this->databaseConnectionFactory->get($selectedDBConfig["dataConnectionName"]);
return new $full_class_name($conn);
}
else {
Expand Down
104 changes: 83 additions & 21 deletions api/src/Page/Shipment.php
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@ function _dispatch_dewar_in_shipping_service($dispatch_info, $dewar)
"internal_contact_name" => $this->has_arg('LOCALCONTACT') ? $this->args['LOCALCONTACT'] : null,
"shipment_reference" => $dispatch_info['VISIT'],
"external_id" => (int) $dispatch_info['DEWARID'],
"journey_type" => "FROM_FACILITY",
"journey_type" => ShippingService::JOURNEY_FROM_FACILITY,
"packages" => array(array("external_id" => (int) $dispatch_info['DEWARID']))
);

Expand All @@ -972,13 +972,13 @@ function _dispatch_dewar_in_shipping_service($dispatch_info, $dewar)
if ($create === true) {
$response = $this->shipping_service->create_shipment($shipment_data);
} else {
$this->shipping_service->update_shipment($dispatch_info['DEWARID'], $shipment_data, "FROM_FACILITY");
$response = $this->shipping_service->get_shipment($dispatch_info['DEWARID'], "FROM_FACILITY");
$this->shipping_service->update_shipment($dispatch_info['DEWARID'], $shipment_data, ShippingService::JOURNEY_FROM_FACILITY);
$response = $this->shipping_service->get_shipment($dispatch_info['DEWARID'], ShippingService::JOURNEY_FROM_FACILITY);
}
$shipment_id = $response['shipmentId'];
$this->shipping_service->dispatch_shipment($shipment_id, false);
} catch (Exception $e) {
throw new Exception("Error returned from shipping service: " . $e . "\nShipment data: " . $shipment_data);
throw new Exception("Error returned from shipping service: " . $e . "\nShipment data: " . json_encode($shipment_data));
}

return $shipment_id;
Expand Down Expand Up @@ -2648,9 +2648,65 @@ function _get_default_dewar()
}


function _book_shipment_in_shipping_service($user, $shipment, $dewars, $journey_type) {
$address_lines = explode(PHP_EOL, rtrim($user["address"]));
$contact = array(
"company_name" => $user["company"],
"address_line1" => isset($address_lines[0]) ? $address_lines[0] : null,
"address_line2" => isset($address_lines[1]) ? $address_lines[1] : null,
"address_line3" => isset($address_lines[2]) ? $address_lines[2] : null,
"city" => $user["city"],
"country" => $user["country"],
"post_code" => rtrim($user["postcode"]),
"contact_name" => $user["name"],
"contact_phone_number" => $user["phone"],
"contact_email" => rtrim($user["email"])
);
$shipment_data = array(
"shipment_reference" => $shipment["PROP"],
"external_id" => $shipment['SHIPPINGID'],
"packages" => array_map(
function($dewar) {return array("external_id" => $dewar["DEWARID"]);},
$dewars
)
);

// Create or update shipment in shipping service
try {
$response = $this->shipping_service->get_shipment($shipment['SHIPPINGID'], $journey_type);
$user_shipment_role = $this->has_arg('RETURN') ? "consignee" : "shipper";
$relabelled_contact = array_combine(
array_map(function($key) use ($user_shipment_role) {return $user_shipment_role."_".$key;},
array_keys($contact)),
$contact);
$shipment_data = array_merge($response, $shipment_data, $relabelled_contact);
$this->shipping_service->update_shipment($shipment["SHIPPINGID"], $shipment_data, ShippingService::JOURNEY_TO_FACILITY);
} catch (\Exception $e) {
$shipment_data["contact"] = $contact;
$response = $this->shipping_service->create_shipment_by_journey_type($shipment_data, $journey_type);
}

// Dispatch shipment in shipping service
$shipmentId = $response["shipmentId"];
$dispatch_details = $this->shipping_service->dispatch_shipment($shipmentId, false);

$awb_pieces = array_map(
function($package, $index) {return array("piecenumber" => $index+1, "licenseplate" => $package["tracking_number"]);},
$dispatch_details["packages"],
array_keys($dispatch_details["packages"])
);

return array(
"awb" => $dispatch_details["tracking_number"],
"label" => $dispatch_details["air_waybill"],
"pieces" => $awb_pieces
);
}


function _create_awb()
{
global $dhl_service, $dhl_service_eu, $dhl_acc, $dhl_acc_import, $facility_courier_countries, $facility_courier_countries_nde;
global $dhl_service, $dhl_service_eu, $dhl_acc, $dhl_acc_import, $facility_courier_countries, $facility_courier_countries_nde, $use_shipping_service_incoming_shipments;

if (!$this->has_arg('prop'))
$this->_error('No proposal specified');
Expand Down Expand Up @@ -2766,22 +2822,28 @@ function _create_awb()
$awb = null;
if (!$ship['DELIVERYAGENT_FLIGHTCODE']) {
try {
$awb = $this->dhl->create_awb(array(
'payee' => $payee,
'accountnumber' => $accno,
'shipperid' => $ship['PROP'],
'service' => $product,
'date' => $ship['DELIVERYAGENT_SHIPPINGDATE'],
'declaredvalue' => $this->arg('DECLAREDVALUE'),
'description' => $this->arg('DESCRIPTION'),

'sender' => $this->has_arg('RETURN') ? $facility : $user,
'receiver' => $this->has_arg('RETURN') ? $user : $facility,

'pieces' => $pieces,
'notification' => implode(';', $emails),
'message' => $facility_company . ': Shipment booked from ISPyB for ' . $ship['PROP'] . ' ' . $ship['SHIPPINGNAME'] . ' containing ' . implode(',', $names)
));
if (Utils::getValueOrDefault($use_shipping_service_incoming_shipments) && $accno === $dhl_acc) {
$journey_type = $this->has_arg('RETURN') ? ShippingService::JOURNEY_FROM_FACILITY : ShippingService::JOURNEY_TO_FACILITY;
$awb = $this->_book_shipment_in_shipping_service($user, $ship, $dewars, $journey_type);
} else {
error_log("Not using shipping service for: {$ship['SHIPPINGID']}");
$awb = $this->dhl->create_awb(array(
'payee' => $payee,
'accountnumber' => $accno,
'shipperid' => $ship['PROP'],
'service' => $product,
'date' => $ship['DELIVERYAGENT_SHIPPINGDATE'],
'declaredvalue' => $this->arg('DECLAREDVALUE'),
'description' => $this->arg('DESCRIPTION'),

'sender' => $this->has_arg('RETURN') ? $facility : $user,
'receiver' => $this->has_arg('RETURN') ? $user : $facility,

'pieces' => $pieces,
'notification' => implode(';', $emails),
'message' => $facility_company . ': Shipment booked from ISPyB for ' . $ship['PROP'] . ' ' . $ship['SHIPPINGNAME'] . ' containing ' . implode(',', $names)
));
}

$this->db->pq("UPDATE shipping
SET deliveryagent_flightcode=:1, deliveryagent_flightcodetimestamp=CURRENT_TIMESTAMP, deliveryagent_label=:2, deliveryagent_productcode=:3, deliveryagent_flightcodepersonid=:4, shippingstatus='awb created', deliveryagent_agentname='DHL'
Expand Down
13 changes: 13 additions & 0 deletions api/src/Shipment/ShippingService.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ class ShippingService
{
private $shipping_api_url;
private $headers;
public const JOURNEY_TO_FACILITY = "TO_FACILITY";
public const JOURNEY_FROM_FACILITY = "FROM_FACILITY";

function __construct()
{
Expand Down Expand Up @@ -77,6 +79,17 @@ function create_shipment($shipment_data)
}


function create_shipment_by_journey_type($shipment_data, $journey_type)
{
return $this->_send_request(
$this->shipping_api_url . '/shipments/' . $journey_type,
"POST",
$shipment_data,
201
);
}


function get_shipment($external_id, $journey_type)
{
return $this->_send_request(
Expand Down
2 changes: 1 addition & 1 deletion api/tests/Database/DatabaseFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public function testErrorIsLoggedForDatabaseTypeClassThatDoesNotExist(): void
{
global $dbtype;
$dbtype = "obscure-db2";
$this->dbFactory->database_types[$dbtype] = $dbtype;
$this->dbFactory->database_types[$dbtype] = ["dbClassName" =>$dbtype, "dataConnectionName" => 'MySQL'];

$log = $this->getFunctionMock(__NAMESPACE__, "error_log");
$log->expects($this->once())->with("Database class 'SynchWeb\Database\Type\obscure-db2' does not exist.");
Expand Down
23 changes: 16 additions & 7 deletions client/src/js/modules/shipment/views/createawb.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,11 +314,19 @@ define(['backbone',
},

checkAvailability: function() {
if (this.shipment.get('DELIVERYAGENT_AGENTNAME').toLowerCase() != 'dhl' && (
!(app.options.get('facility_courier_countries').indexOf(this.lc.get('COUNTRY')) > -1) &&
!(app.options.get('facility_courier_countries_nde').indexOf(this.lc.get('COUNTRY')) > -1)
))
app.message({ title: 'Service Not Available', message: 'This service is only available for shipments from '+app.options.get('facility_courier_countries').concat(app.options.get('facility_courier_countries_nde')).join(',')+', or for user with DHL accounts. Please either update your labcontact or the shipment courier'})
const agent_name = this.shipment.get('DELIVERYAGENT_AGENTNAME')
const facility_courier_countries = app.options.get('facility_courier_countries')
const facility_courier_countries_nde = app.options.get('facility_courier_countries_nde')
if ((agent_name==null || agent_name.toLowerCase() != 'dhl') && (
!(facility_courier_countries.indexOf(this.lc.get('COUNTRY')) > -1) &&
!(facility_courier_countries_nde.indexOf(this.lc.get('COUNTRY')) > -1)
)) {
const valid_countries = facility_courier_countries.concat(facility_courier_countries_nde).join(', ')
app.message({
title: 'Service Not Available',
message: 'This service is only available for shipments from ' + valid_countries +
', or for user with DHL accounts. Please either update your labcontact or the shipment courier'})
}
},

populateLC: function() {
Expand Down Expand Up @@ -435,7 +443,7 @@ define(['backbone',
PRODUCTCODE: prod,
},
success: function(resp) {
app.alert({ message: 'Air Waybill Successfully Created'})
app.message({ message: 'Air Waybill Successfully Created'})
setTimeout(function() {
app.trigger('shipment:show', self.shipment.get('SHIPPINGID'))
}, 1000)
Expand All @@ -452,7 +460,8 @@ define(['backbone',
console.error("Error parsing response: ", err)
}
}
app.alert({ message: json.message })
app.alert({ message: json.message, persist:true })
app.alert({ message: json.message})
self.ui.submit.prop('disabled', false)
self.$el.removeClass('loading')
}
Expand Down
2 changes: 2 additions & 0 deletions client/src/js/modules/shipment/views/dispatch.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ define(['marionette', 'views/form',
this.ui.exp.html(this.visits.opts()).val(this.model.get('VISIT'))
this.updateLC()
this.populateCountries()
this.stripPostCode()
this.formatAddress()
},

populateCountries: function() {
Expand Down
2 changes: 1 addition & 1 deletion client/src/js/templates/contact/contactview.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ <h1>View Home Lab Contact</h1>
</li>

<li class="clearfix">
<span class="label">Street Address <br />(excluding post code, city)</span>
<span class="label">Street Address <br />(Max 3 lines, excluding post code, city)</span>
<div class="ADDRESS text editable tw-block"><%-ADDRESS%></div>
</li>

Expand Down
2 changes: 1 addition & 1 deletion client/src/js/templates/shipment/createawb.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ <h2>Laboratory Details</h2>
</li>

<li class="clearfix">
<span class="label">Laboratory Address <br /><span class="small">(excluding post code)</span></span>
<span class="label">Laboratory Address <br /><span class="small">(Max 3 lines, excluding post code, city)</span></span>
<div class="ADDRESS text"></div>
</li>

Expand Down
Loading