Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/config_sample.php
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@

# Shipping service details
$use_shipping_service = null;
$use_shipping_service_nde = False;
$use_shipping_service_incoming_shipments = null;
$use_shipping_service_redirect = null;
$use_shipping_service_redirect_incoming_shipments = null;
Expand Down
4 changes: 3 additions & 1 deletion api/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ function setupApplication($mode): Slim
$visit_persist_storage_dir_segment, $dhl_enable, $scale_grid, $scale_grid_end_date, $preset_proposal, $timezone,
$valid_components, $enabled_container_types, $synchweb_version, $redirects,
$shipping_service_app_url, $use_shipping_service_redirect, $use_shipping_service_redirect_incoming_shipments,
$use_shipping_service_nde,
$dials_rest_url_rings, $closed_proposal_link, $ccp4_cloud_upload_url,
$only_staff_can_assign, $industrial_prop_codes, $upstream_reprocessing_pipelines, $downstream_reprocessing_pipelines,
$prop_codes_data_deleted, $container_types_with_parents, $bl_capacity;
Expand Down Expand Up @@ -99,8 +100,9 @@ function setupApplication($mode): Slim
'enabled_container_types' => $enabled_container_types,
'synchweb_version' => $synchweb_version,
'redirects' => $redirects,
'shipping_service_app_url' => $use_shipping_service_redirect || $use_shipping_service_redirect_incoming_shipments ? $shipping_service_app_url : null,
'shipping_service_app_url' => $use_shipping_service_redirect ? $shipping_service_app_url : null,
'shipping_service_app_url_incoming' => $use_shipping_service_redirect_incoming_shipments ? $shipping_service_app_url : null,
'use_shipping_service_nde' => $use_shipping_service_nde,
'dials_rest_url_rings' => $dials_rest_url_rings,
'closed_proposal_link' => $closed_proposal_link,
'ccp4_cloud_upload_url' => $ccp4_cloud_upload_url,
Expand Down
141 changes: 102 additions & 39 deletions api/src/Page/Shipment.php
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ class Shipment extends Page

array('/dewars/transfer', 'post', '_transfer_dewar'),
array('/dewars/dispatch', 'post', '_dispatch_dewar'),
array('/dewars/confirmdispatch/did/:did/token/:TOKEN', 'post', '_dispatch_dewar_confirmation'),
array('/dewars/confirmdispatch/did/:did/token/:TOKEN', 'post', '_outgoing_shipment_confirmation'),
array('/dewars/confirmpickup/sid/:sid/token/:TOKEN', 'post', '_incoming_shipment_confirmation'),

array('/dewars/tracking(/:DEWARID)', 'get', '_get_dewar_tracking'),
Expand Down Expand Up @@ -1180,11 +1180,11 @@ function _dispatch_dewar_in_shipping_service($dispatch_info, $dewar)
function _dispatch_dewar()
{
global $facility_country;
global $facility_courier_countries;
global $facility_courier_countries, $facility_courier_countries_nde;
global $dispatch_email;
global $dispatch_email_regex;
global $dispatch_email_intl;
global $use_shipping_service;
global $use_shipping_service, $use_shipping_service_nde;
global $shipping_service_links_in_emails;
global $use_shipping_service_redirect;
global $shipping_service_app_url;
Expand Down Expand Up @@ -1266,7 +1266,10 @@ function _dispatch_dewar()
$data = $this->args;
$data['TERMSACCEPTED'] = $terms_accepted;

if (Utils::getValueOrDefault($use_shipping_service) && in_array($country, $facility_courier_countries)) {
$domestic = in_array($country, $facility_courier_countries);
$nde = $use_shipping_service_nde && in_array($country, $facility_courier_countries_nde);

if (Utils::getValueOrDefault($use_shipping_service) && ($domestic || $nde)) {
if ($terms_accepted) {
if (Utils::getValueOrDefault($use_shipping_service_redirect)) {
try {
Expand Down Expand Up @@ -1300,7 +1303,7 @@ function _dispatch_dewar()
# Prepare e-mail response for dispatch request
$use_dispatch_lite_template = (
Utils::getValueOrDefault($use_shipping_service)
&& in_array($country, $facility_courier_countries)
&& ($domestic || $nde)
&& $terms_accepted
&& Utils::getValueOrDefault($use_shipping_service_redirect)
);
Expand Down Expand Up @@ -1389,16 +1392,30 @@ function _dispatch_dewar()
}
}

function _outgoing_shipment_confirmation()
{
if (!$this->has_arg('did'))
$this->_error('No dewar specified');
if (!$this->has_arg('TOKEN'))
$this->_error('No token specified');
if (!$this->has_arg('status'))
$this->_error('No status specified');

if ($this->arg('status') === 'CREATED') {
$this->_cancel_dispatch_dewar_confirmation();
} else if ($this->arg('status') === 'BOOKED' || $this->arg('status') === 'PENDING') {
$this->_dispatch_dewar_confirmation();
} else {
$this->_error('Invalid status');
}
}

function _dispatch_dewar_confirmation()
{
global $dispatch_email;
global $dispatch_email_regex;
global $shipping_service_app_url;

if (!$this->has_arg('did'))
$this->_error('No dewar specified');

# Check token against dewar given
$dew = $this->db->pq(
"SELECT d.dewarid, d.barcode, d.storagelocation, d.dewarstatus, d.externalShippingIdFromSynchrotron, d.facilitycode, d.trackingNumberFromSynchrotron,
Expand All @@ -1420,7 +1437,18 @@ function _dispatch_dewar_confirmation()
$this->_error('Incorrect token');
}

# Prepare e-mail to stores
if ($this->arg('status') === 'BOOKED') {
if (!$this->has_arg('tracking_number'))
$this->_error('No tracking number specified');
$tracking = $this->arg('tracking_number');
$status = 'dispatch-booked';
} else if ($this->arg('status') === 'PENDING') {
$tracking = '';
$status = 'dispatch-requested';
} else {
$this->_error('Invalid status');
}

$data = $this->args;
if (!array_key_exists('prop', $data))
$data['prop'] = $dew['PROPOSAL'];
Expand All @@ -1434,54 +1462,89 @@ function _dispatch_dewar_confirmation()
$data['LOCATION'] = $dew['STORAGELOCATION'];
if (!array_key_exists('EMAILADDRESS', $data))
$data['EMAILADDRESS'] = $dew['EMAILADDRESS'];;
if (!array_key_exists('tracking_number', $data))
$data['tracking_number'] = $dew['TRACKINGNUMBERFROMSYNCHROTRON'];
$subject_line = '*** Dispatch requested for Dewar ' . $dew['BARCODE'] . ' from ' . $data['LOCATION'] . ' ***';
$email_template = 'dewar-dispatch-lite';
$email = new Email($email_template, $subject_line);
$email->data = $data;

// If a local contact is given, try to find their email address
// First try LDAP, if unsuccessful look at the ISPyB person record for a matching staff user
$local_contact = $this->has_arg('LOCALCONTACT') ? $this->args['LOCALCONTACT'] : '';
if ($local_contact) {
$this->args['LCEMAIL'] = $this->_get_email_fn($local_contact);
if (!$this->args['LCEMAIL']) {
$this->args['LCEMAIL'] = $this->_get_ispyb_email_fn($local_contact);
if ($this->arg('status') === 'BOOKED') {
# Prepare e-mail to stores
$subject_line = '*** Dispatch requested for Dewar ' . $dew['BARCODE'] . ' from ' . $data['LOCATION'] . ' ***';
$email_template = 'dewar-dispatch-lite';
$email = new Email($email_template, $subject_line);
$email->data = $data;

// If a local contact is given, try to find their email address
// First try LDAP, if unsuccessful look at the ISPyB person record for a matching staff user
$local_contact = $this->has_arg('LOCALCONTACT') ? $this->args['LOCALCONTACT'] : '';
if ($local_contact) {
$this->args['LCEMAIL'] = $this->_get_email_fn($local_contact);
if (!$this->args['LCEMAIL']) {
$this->args['LCEMAIL'] = $this->_get_ispyb_email_fn($local_contact);
}
}
}

$recpts = $dispatch_email;
if ($data['EMAILADDRESS']) $recpts .= ', ' . $data['EMAILADDRESS'];
$local_contact_email = $this->has_arg('LCEMAIL') ? $this->args['LCEMAIL'] : '';
if ($local_contact_email) $recpts .= ', ' . $local_contact_email;
$recpts = $dispatch_email;
if ($data['EMAILADDRESS']) $recpts .= ', ' . $data['EMAILADDRESS'];
$local_contact_email = $this->has_arg('LCEMAIL') ? $this->args['LCEMAIL'] : '';
if ($local_contact_email) $recpts .= ', ' . $local_contact_email;

if (!is_null($dispatch_email_regex)) {
foreach ($dispatch_email_regex as $address => $pattern) {
if (preg_match($pattern, $data['BARCODE'])) {
$recpts .= ', ' . $address;
if (!is_null($dispatch_email_regex)) {
foreach ($dispatch_email_regex as $address => $pattern) {
if (preg_match($pattern, $data['BARCODE'])) {
$recpts .= ', ' . $address;
}
}
}
}

$email->send($recpts);
$email->send($recpts);
}

// Also update the dewar status and storage location to keep it in sync with history...
$this->db->pq(
"UPDATE dewar
set dewarstatus='dispatch-requested', storagelocation=lower(:2), trackingnumberfromsynchrotron=:3
WHERE dewarid=:1",
array($dew['DEWARID'], $data['LOCATION'], $data['tracking_number'])
set dewarstatus=:1, storagelocation=lower(:2), trackingnumberfromsynchrotron=:3
WHERE dewarid=:4",
array($status, $data['LOCATION'], $tracking, $dew['DEWARID'])
);

$this->db->pq("UPDATE shipping set shippingstatus='dispatch-requested' WHERE shippingid=:1", array($dew['SHIPPINGID']));
$this->db->pq("UPDATE shipping set shippingstatus=:1 WHERE shippingid=:2", array($status, $dew['SHIPPINGID']));

// Update dewar transport history with provided location.
$this->db->pq(
"INSERT INTO dewartransporthistory (dewartransporthistoryid,dewarid,dewarstatus,storagelocation,arrivaldate)
VALUES (s_dewartransporthistory.nextval,:1,'dispatch-requested',:2,CURRENT_TIMESTAMP)
VALUES (s_dewartransporthistory.nextval,:1,:2,:3,CURRENT_TIMESTAMP)
RETURNING dewartransporthistoryid INTO :id",
array($dew['DEWARID'], $status, $data['LOCATION'])
);

$this->_output(1);
}

function _cancel_dispatch_dewar_confirmation()
{
// Check token against dewar
$dew = $this->db->pq(
"SELECT d.dewarid, d.shippingid, json_unquote(json_extract(d.extra, '$.token')) as token, storagelocation
FROM dewar d
WHERE d.dewarid=:1",
array($this->arg('did'))
);

$dew = $dew[0];

if (!$this->has_arg('TOKEN') || $this->arg('TOKEN') !== $dew['TOKEN']) {
$this->_error('Incorrect token');
}

$this->db->pq("UPDATE shipping set shippingstatus='dispatch request cancelled' WHERE shippingid=:1", array($dew['SHIPPINGID']));

// Update the dewar status
$this->db->pq("UPDATE dewar set dewarstatus='dispatch request cancelled' WHERE dewarid=:1", array($dew['DEWARID']));

// Update dewar transport history
$loc = Utils::getValueOrDefault($dew['STORAGELOCATION'], '');
$this->db->pq(
"INSERT INTO dewartransporthistory (dewartransporthistoryid,dewarid,dewarstatus,storagelocation,arrivaldate)
VALUES (s_dewartransporthistory.nextval,:1,'dispatch request cancelled',:2,CURRENT_TIMESTAMP)
RETURNING dewartransporthistoryid INTO :id",
array($dew['DEWARID'], $data['LOCATION'])
array($dew['DEWARID'], $loc)
);

$this->_output(1);
Expand Down
2 changes: 2 additions & 0 deletions client/src/js/modules/shipment/views/dewars.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ define(['marionette', 'backbone',
if (app.options.get('shipping_service_app_url') && this.model.get('EXTERNALSHIPPINGIDFROMSYNCHROTRON')) {
let link = app.options.get('shipping_service_app_url')+'/shipment-requests/'+this.model.get('EXTERNALSHIPPINGIDFROMSYNCHROTRON')+'/outgoing'
this.ui.ssd.attr('href', link)
this.ui.dispatch.hide()
this.ui.transfer.hide()
} else {
this.ui.ssd.hide()
}
Expand Down
42 changes: 20 additions & 22 deletions client/src/js/modules/shipment/views/dispatch.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,7 @@ define(['marionette', 'views/form',
},

success: function() {
if (
app.options.get("shipping_service_app_url")
&& (Number(this.terms.get('ACCEPTED')) === 1) // terms.ACCEPTED could be undefined, 1, or "1"
&& app.options.get("facility_courier_countries").includes(this.dispatchCountry)
) {
if (this.usingShippingService()) {
this.getOption('dewar').fetch().done((dewar) => {
const external_id = dewar.EXTERNALSHIPPINGIDFROMSYNCHROTRON;
if (external_id === null){
Expand Down Expand Up @@ -289,21 +285,29 @@ define(['marionette', 'views/form',
this.ui.facc.show()
}

if (
this.terms.get("ACCEPTED")
&& app.options.get("shipping_service_app_url")
&& app.options.get("facility_courier_countries").includes(this.dispatchCountry)
){
this.disableValidation()
this.ui.dispatchDetails.hide()
this.ui.submit.text("Proceed")
this.ui.shippingadvice.html("<mark>On clicking 'Proceed' you will be redirected to the new Diamond shipping service to book the shipment. Please ensure all stages of the form are completed.</mark><br /><br />")
if (this.usingShippingService()) {
this.useShortFormForShippingService()
} else {
this.ui.submit.text("Request Dewar Dispatch")
this.ui.shippingadvice.html("")
}
},

usingShippingService: function() {
const domestic = app.options.get("facility_courier_countries").includes(this.ui.country.val())
const nde = app.options.get("use_shipping_service_nde") && app.options.get("facility_courier_countries_nde").includes(this.ui.country.val())
return this.terms.get("ACCEPTED")
&& app.options.get("shipping_service_app_url")
&& (domestic || nde)
},

useShortFormForShippingService: function() {
this.disableValidation()
this.ui.dispatchDetails.hide()
this.ui.submit.text("Proceed")
this.ui.shippingadvice.html("<mark>On clicking 'Proceed' you will be redirected to the new Diamond shipping service to book the shipment. Please ensure all stages of the form are completed.</mark><br /><br />")
},

enableValidation: function() {
this.model.visitRequired = true
this.model.dispatchDetailsRequired = true
Expand Down Expand Up @@ -358,14 +362,8 @@ define(['marionette', 'views/form',
this.ui.courierDetails.hide()
this.ui.facilityCourier.show()
this.model.courierDetailsRequired = false
if (
app.options.get("shipping_service_app_url")
&& app.options.get("facility_courier_countries").includes(this.ui.country.val())
){
this.disableValidation()
this.ui.dispatchDetails.hide()
this.ui.submit.text("Proceed")
this.ui.shippingadvice.html("<mark>On clicking 'Proceed' you will be redirected to the new Diamond shipping service to book the shipment. Please ensure all stages of the form are completed.</mark><br /><br />")
if (this.usingShippingService()) {
this.useShortFormForShippingService()
}
},

Expand Down
4 changes: 2 additions & 2 deletions client/src/js/utils/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ define(['backbone', 'backbone-validation'], function(Backbone) {
sequence: /^[>;\s\w+\n\(\)\.\|]+$/,
address: /^(\w|\s|\-|\n|,)+$/,
array: /^[\d+(.\d+)?),]+$/,
country: /^(\w|\s|\-|,|\(|\)|')+$/,
country: /^(\w|\s|\-|,|\(|\)|'|\.)+$/,
visit: /^\w+\d+-\d+$/,
visitornull: /^\w+\d+-\d+$|^(?![\s\S])/,
twopath: /^(\w|-)+\/?(\w|-)+$/,
Expand All @@ -38,7 +38,7 @@ define(['backbone', 'backbone-validation'], function(Backbone) {
sequence: 'This field may only contain word characters and line returns',
address: 'This field may only contain word character, spaces, and line returns',
array: 'This field may only contain numbers and commas',
country: 'This field must contain only letters, numbers, spaces, underscores, dashes, and commas',
country: 'This field must contain only letters, numbers, spaces, underscores, dashes, dots and commas',
visit: 'This field must be of the format xxx123-123',
visitornull: 'This field must be of the format xxx123-123 or a null value',
twopath: 'This field can hold a path with two folders',
Expand Down
Loading