diff --git a/api/config_sample.php b/api/config_sample.php
index 0b53beb4e..26ab1c17f 100644
--- a/api/config_sample.php
+++ b/api/config_sample.php
@@ -310,6 +310,9 @@
# - If these are not defined for a proposal type, the api then uses bl_types below
$prop_types = array('mx');
+ # Industrial proposals are not allowed to use the facility shipping account
+ $industrial_prop_codes = array('sw', 'in', 'ic');
+
# This maps beamlinename in blsession to a proposal type
# - Internal maps a beamline to an api "type", there are currently:
# mx, gen, em
diff --git a/api/index.php b/api/index.php
index ee9c612a3..dcfd3519c 100644
--- a/api/index.php
+++ b/api/index.php
@@ -73,7 +73,7 @@ function setupApplication($mode): Slim
$valid_components, $enabled_container_types, $synchweb_version, $redirects,
$shipping_service_app_url, $use_shipping_service_redirect, $use_shipping_service_redirect_incoming_shipments,
$dials_rest_url_rings, $closed_proposal_link, $ccp4_cloud_upload_url,
- $only_staff_can_assign;
+ $only_staff_can_assign, $industrial_prop_codes;
$app->contentType('application/json');
$options = $app->container['options'];
$app->response()->body(json_encode(array(
@@ -102,7 +102,8 @@ function setupApplication($mode): Slim
'dials_rest_url_rings' => $dials_rest_url_rings,
'ccp4_cloud_upload_url' => $ccp4_cloud_upload_url,
'redirects' => $redirects,
- 'only_staff_can_assign' => $only_staff_can_assign
+ 'only_staff_can_assign' => $only_staff_can_assign,
+ 'industrial_prop_codes' => $industrial_prop_codes
)));
});
return $app;
diff --git a/api/src/Page/Shipment.php b/api/src/Page/Shipment.php
index d8e753f9e..209a24e79 100644
--- a/api/src/Page/Shipment.php
+++ b/api/src/Page/Shipment.php
@@ -1734,7 +1734,8 @@ function _get_dewars()
d.code, d.barcode, d.storagelocation, d.dewarstatus, d.dewarid,
d.trackingnumbertosynchrotron, d.trackingnumberfromsynchrotron, d.externalShippingIdFromSynchrotron,
s.deliveryagent_agentname, d.weight, d.deliveryagent_barcode, GROUP_CONCAT(c.code SEPARATOR ', ') as containers,
- s.sendinglabcontactid, s.returnlabcontactid, pe.givenname, pe.familyname, s.safetylevel as shippingsafetylevel
+ s.sendinglabcontactid, s.returnlabcontactid, pe.givenname, pe.familyname, s.safetylevel as shippingsafetylevel,
+ s.extra
FROM dewar d
LEFT OUTER JOIN container c ON c.dewarid = d.dewarid
INNER JOIN shipping s ON d.shippingid = s.shippingid
@@ -1748,6 +1749,18 @@ function _get_dewars()
GROUP BY CONCAT(p.proposalcode, p.proposalnumber, '-', se.visit_number), r.labcontactid, se.beamlineoperator, TO_CHAR(se.startdate, 'HH24:MI DD-MM-YYYY'), (case when se.visit_number > 0 then (CONCAT(p.proposalcode, p.proposalnumber, '-', se.visit_number)) else '' end),s.shippingid, s.shippingname, d.code, d.barcode, d.storagelocation, d.dewarstatus, d.dewarid, d.trackingnumbertosynchrotron, d.trackingnumberfromsynchrotron, d.facilitycode, d.firstexperimentid
ORDER BY $order", $args);
+ foreach ($dewars as &$s) {
+ $extra_json = json_decode($s['EXTRA'], true);
+ if (is_null($extra_json)) {
+ $extra_json = array();
+ foreach ($this->extra_arg_list as $arg) {
+ $extra_json[$arg] = "";
+ }
+ }
+ $s = array_merge($s, $extra_json);
+ }
+
+
if ($this->has_arg('did')) {
if (sizeof($dewars))
$this->_output($dewars[0]);
diff --git a/client/src/js/modules/shipment/views/dewars.js b/client/src/js/modules/shipment/views/dewars.js
index c853b3a4e..70a7726eb 100644
--- a/client/src/js/modules/shipment/views/dewars.js
+++ b/client/src/js/modules/shipment/views/dewars.js
@@ -41,6 +41,7 @@ define(['marionette', 'backbone',
dispatch: '.dispatch',
transfer: '.transfer',
ssd: '.ssdispatch',
+ addcont: '.add-container-small',
},
className: function() {
@@ -126,6 +127,7 @@ define(['marionette', 'backbone',
this.ui.fc.html(this.getOption('regdewars').opts({ empty: true }))
this.showHideButtons()
+ this.listenTo(this.model, 'change', this.showHideButtons)
},
showHideButtons: function() {
@@ -148,6 +150,11 @@ define(['marionette', 'backbone',
} else {
this.ui.ssd.hide()
}
+ if (this.model.get('DYNAMIC') === 'Ready') {
+ this.ui.addcont.hide()
+ } else {
+ this.ui.addcont.show()
+ }
},
modelEvents: {
diff --git a/client/src/js/modules/shipment/views/dispatch.js b/client/src/js/modules/shipment/views/dispatch.js
index dafa0c578..3304e00b6 100644
--- a/client/src/js/modules/shipment/views/dispatch.js
+++ b/client/src/js/modules/shipment/views/dispatch.js
@@ -156,12 +156,6 @@ define(['marionette', 'views/form',
this.$el.find('input[name=DELIVERYAGENT_SHIPPINGDATE]').val(today)
this.$el.find('.facilityCourier').hide()
- industrial_codes = ['in', 'sw']
- industrial_visit = industrial_codes.includes(app.prop.slice(0,2))
- if (industrial_visit) {
- this.ui.facc.hide()
- }
-
if (this.shipping.get('TERMSACCEPTED') == 0) {
this.ui.courier.val(this.shipping.get('DELIVERYAGENT_AGENTNAME'))
this.ui.accountNumber.val(this.shipping.get('DELIVERYAGENT_AGENTCODE'))
@@ -280,7 +274,12 @@ define(['marionette', 'views/form',
this.ui.dispatchDetails.show();
this.enableValidation()
this.ui.submit.show();
+
+ industrial_codes = app.options.get('industrial_prop_codes')
+ industrial_visit = industrial_codes.includes(app.prop.slice(0,2))
+
if (
+ industrial_visit ||
this.terms.get("ACCEPTED") ||
(!app.options.get("facility_courier_countries").includes(this.dispatchCountry) &&
!app.options.get("facility_courier_countries_nde").includes(this.dispatchCountry))
@@ -289,6 +288,7 @@ define(['marionette', 'views/form',
} else {
this.ui.facc.show()
}
+
if (
this.terms.get("ACCEPTED")
&& app.options.get("shipping_service_app_url")
diff --git a/client/src/js/modules/shipment/views/shipment.js b/client/src/js/modules/shipment/views/shipment.js
index 3be8f6048..ad561dd87 100644
--- a/client/src/js/modules/shipment/views/shipment.js
+++ b/client/src/js/modules/shipment/views/shipment.js
@@ -50,11 +50,14 @@ define(['marionette',
'click a.send': 'sendShipment',
'click a.pdf': utils.signHandler,
'click a.cancel_pickup': 'cancelPickup',
+ 'click a.ready': 'markAsReady',
},
ui: {
add_dewar: '#add_dewar',
longwavelength: '.longwavelength',
+ ready: '.ready',
+ dynamic: '.DYNAMIC',
sent: '.sent',
booking: '.booking',
dhlmessage: '.dhlmessage',
@@ -173,6 +176,23 @@ define(['marionette',
this.fetchDewars(true)
},
+ markAsReady: function(e) {
+ e.preventDefault()
+ utils.confirm({
+ title: 'Ready for Scheduling',
+ content: 'Are you sure you want to mark the shipment as ready for scheduling?
'+
+ 'We ask users to define all samples prior to shipping any dewar to us. We can schedule dewars before they arrive, once we have confirmation that the dewar is ready to be loaded onto a beamline.
'+
+ 'Once you confirm that the shipment is finalised, you will not be able to add dewars or pucks.
'+
+ 'If you have any questions, please email your local contact.',
+ callback: this.doMarkAsReady.bind(this)
+ })
+ },
+
+ doMarkAsReady: function() {
+ this.model.save({ DYNAMIC: 'Ready' }, { patch: true })
+ if (!app.staff) this.edit.remove('DYNAMIC')
+ },
+
updateGUI: function() {
this.updateCountryFromLabContact()
this.showButtons()
@@ -262,14 +282,23 @@ define(['marionette',
updateDynamic: function(){
dynamic = this.model.get('DYNAMIC')
dynamicSelectedValues = [true, 'Yes', 'yes', 'Y', 'y']
- if (!dynamicSelectedValues.includes(dynamic)) {
+ this.ui.ready.hide()
+ if (dynamic === 'Ready') {
+ this.ui.dynamic.html('I would like a session to be scheduled - my shipment is ready for scheduling')
+ } else if (dynamicSelectedValues.includes(dynamic)) {
+ this.ui.dynamic.html(this.dynamicOptions['Yes'])
+ if (!this.industrial_visit) {
+ this.ui.ready.show()
+ }
+ } else {
+ this.ui.dynamic.html(this.dynamicOptions[dynamic])
+ }
+ if (!dynamicSelectedValues.includes(dynamic) && dynamic !== 'Ready') {
this.$el.find(".remoteormailin").hide()
this.$el.find(".remoteform").hide()
this.ui.longwavelength.hide()
} else {
- industrial_codes = ['in', 'sw']
- industrial_visit = industrial_codes.includes(app.prop.slice(0,2))
- if (industrial_visit) {
+ if (this.industrial_visit) {
this.$el.find(".remoteormailin").show()
}
this.ui.longwavelength.show()
@@ -279,10 +308,22 @@ define(['marionette',
this.$el.find(".remoteform").show()
}
}
+ if (dynamic === 'Ready' || (app.proposal && app.proposal.get('ACTIVE') != '1')) {
+ this.ui.add_dewar.hide()
+ } else {
+ this.ui.add_dewar.show()
+ }
+
+ if (this.dewars) {
+ this.dewars.each(function(dewar) {
+ if (dewar.get('DYNAMIC') !== dynamic) {
+ dewar.set('DYNAMIC', dynamic)
+ }
+ })
+ }
},
onRender: function() {
- if (app.proposal && app.proposal.get('ACTIVE') != '1') this.ui.add_dewar.hide()
this.table.show(new DewarsView({ collection: this.dewars }))
this.cont.show(new DewarContentView({ collection: this.dewarcontent }))
@@ -291,46 +332,49 @@ define(['marionette',
this.listenTo(this.cont.currentView, 'refresh:dewars', this.refreshDewar, this)
- var edit = new Editable({ model: this.model, el: this.$el })
- edit.create('SHIPPINGNAME', 'textlong')
- edit.create('SAFETYLEVEL', 'select', { data: {'Green': 'Green', 'Yellow':'Yellow', 'Red': 'Red'}, alert: true, revert: true })
- edit.create('COMMENTS', 'textarea')
- edit.create('DELIVERYAGENT_AGENTNAME', 'text')
- edit.create('DELIVERYAGENT_AGENTCODE', 'text')
- edit.create('DELIVERYAGENT_SHIPPINGDATE', 'date')
- edit.create('DELIVERYAGENT_DELIVERYDATE', 'date')
- edit.create('DELIVERYAGENT_FLIGHTCODE', 'text')
- edit.create('PHYSICALLOCATION', 'text')
- edit.create('READYBYTIME', 'time')
- edit.create('CLOSETIME', 'time')
-
-
- edit.create("ENCLOSEDHARDDRIVE", 'select', { data: {'Yes': 'Yes', 'No': 'No'}})
- edit.create("ENCLOSEDTOOLS", 'select', { data: {'Yes': 'Yes', 'No': 'No'}})
- edit.create("DYNAMIC", 'select', { data: {
+ this.edit = new Editable({ model: this.model, el: this.$el })
+ this.edit.create('SHIPPINGNAME', 'textlong')
+ this.edit.create('SAFETYLEVEL', 'select', { data: {'Green': 'Green', 'Yellow':'Yellow', 'Red': 'Red'}, alert: true, revert: true })
+ this.edit.create('COMMENTS', 'textarea')
+ this.edit.create('DELIVERYAGENT_AGENTNAME', 'text')
+ this.edit.create('DELIVERYAGENT_AGENTCODE', 'text')
+ this.edit.create('DELIVERYAGENT_SHIPPINGDATE', 'date')
+ this.edit.create('DELIVERYAGENT_DELIVERYDATE', 'date')
+ this.edit.create('DELIVERYAGENT_FLIGHTCODE', 'text')
+ this.edit.create('PHYSICALLOCATION', 'text')
+ this.edit.create('READYBYTIME', 'time')
+ this.edit.create('CLOSETIME', 'time')
+
+
+ this.edit.create("ENCLOSEDHARDDRIVE", 'select', { data: {'Yes': 'Yes', 'No': 'No'}})
+ this.edit.create("ENCLOSEDTOOLS", 'select', { data: {'Yes': 'Yes', 'No': 'No'}})
+ this.dynamicOptions = {
'No': 'I have a session already scheduled',
'UDC': 'I am sending pucks for Unattended Data Collection',
'Imaging': 'I am sending plates for imaging',
'Yes': 'I would like a session to be scheduled',
'Other': 'Something else',
- }})
- industrial_codes = ['in', 'sw']
- industrial_visit = industrial_codes.includes(app.prop.slice(0,2))
- if (!industrial_visit) {
+ }
+ if (app.staff || this.model.get('DYNAMIC') !== 'Ready') {
+ this.edit.create('DYNAMIC', 'select', { data: this.dynamicOptions})
+ }
+ industrial_codes = app.options.get('industrial_prop_codes')
+ this.industrial_visit = industrial_codes.includes(app.prop.slice(0,2))
+ if (!this.industrial_visit) {
this.$el.find(".remoteormailin").hide()
} else {
- edit.create("REMOTEORMAILIN", 'select', { data: {'Remote': 'Remote', 'Mail-in': 'Mail-in', 'Other': 'Other'}})
+ this.edit.create("REMOTEORMAILIN", 'select', { data: {'Remote': 'Remote', 'Mail-in': 'Mail-in', 'Other': 'Other'}})
}
- edit.create("LONGWAVELENGTH", 'select', { data: {'Yes': 'Yes', 'No': 'No'}})
- edit.create("SESSIONLENGTH", 'text')
- edit.create("ENERGY", 'text')
- edit.create("MICROFOCUSBEAM", 'select', { data: {'Yes': 'Yes', 'No': 'No'}})
- edit.create("SCHEDULINGRESTRICTIONS", 'text')
- edit.create("LASTMINUTEBEAMTIME", 'select', { data: {'Yes': 'Yes', 'No': 'No'}})
- edit.create("DEWARGROUPING", 'select', { data: {'Yes': 'Yes', 'No': 'No', 'Don\'t mind': 'Don\'t mind'}})
- edit.create("EXTRASUPPORTREQUIREMENT", 'text');
- edit.create("MULTIAXISGONIOMETRY", 'select', { data: {'Yes': 'Yes', 'No': 'No'}})
+ this.edit.create("LONGWAVELENGTH", 'select', { data: {'Yes': 'Yes', 'No': 'No'}})
+ this.edit.create("SESSIONLENGTH", 'text')
+ this.edit.create("ENERGY", 'text')
+ this.edit.create("MICROFOCUSBEAM", 'select', { data: {'Yes': 'Yes', 'No': 'No'}})
+ this.edit.create("SCHEDULINGRESTRICTIONS", 'text')
+ this.edit.create("LASTMINUTEBEAMTIME", 'select', { data: {'Yes': 'Yes', 'No': 'No'}})
+ this.edit.create("DEWARGROUPING", 'select', { data: {'Yes': 'Yes', 'No': 'No', 'Don\'t mind': 'Don\'t mind'}})
+ this.edit.create("EXTRASUPPORTREQUIREMENT", 'text');
+ this.edit.create("MULTIAXISGONIOMETRY", 'select', { data: {'Yes': 'Yes', 'No': 'No'}})
this.updateGUI()
this.listenTo(this.model, "change", this.updateGUI)
@@ -340,8 +384,8 @@ define(['marionette',
this.contacts = new LabContacts(null, { state: { pageSize: 9999 } })
this.contacts.fetch().done(function() {
console.log(self.contacts, self.contacts.kv())
- edit.create('SENDINGLABCONTACTID', 'select', { data: self.contacts.kv() })
- edit.create('RETURNLABCONTACTID', 'select', { data: self.contacts.kv() })
+ self.edit.create('SENDINGLABCONTACTID', 'select', { data: self.contacts.kv() })
+ self.edit.create('RETURNLABCONTACTID', 'select', { data: self.contacts.kv() })
})
},
diff --git a/client/src/js/modules/shipment/views/shipmentadd.js b/client/src/js/modules/shipment/views/shipmentadd.js
index a55231c42..8eb5f00d4 100644
--- a/client/src/js/modules/shipment/views/shipmentadd.js
+++ b/client/src/js/modules/shipment/views/shipmentadd.js
@@ -169,7 +169,7 @@ define(['marionette', 'views/form',
},
isIndustrialProposal: function() {
- industrial_codes = ['in', 'sw']
+ industrial_codes = app.options.get('industrial_prop_codes')
return industrial_codes.includes(app.prop.slice(0,2))
},
diff --git a/client/src/js/templates/shipment/shipment.html b/client/src/js/templates/shipment/shipment.html
index fb8fb8fe9..6cf069643 100644
--- a/client/src/js/templates/shipment/shipment.html
+++ b/client/src/js/templates/shipment/shipment.html
@@ -100,26 +100,6 @@