diff --git a/api/src/Page.php b/api/src/Page.php index a5ee4c334..efb2d1cbb 100644 --- a/api/src/Page.php +++ b/api/src/Page.php @@ -649,6 +649,11 @@ function argOrNull($key) return $this->has_arg($key) ? $this->arg($key) : null; } + function argIfNotEmptyString($key) + { + return $this->has_arg($key) && $this->arg($key) !== '' ? $this->arg($key) : null; + } + # ------------------------------------------------------------------------ # Misc Helpers diff --git a/api/src/Page/Shipment.php b/api/src/Page/Shipment.php index 0019c1e77..31637312f 100644 --- a/api/src/Page/Shipment.php +++ b/api/src/Page/Shipment.php @@ -2607,8 +2607,8 @@ function _add_container() $tem = $this->has_arg('STORAGETEMPERATURE') ? $this->arg('STORAGETEMPERATURE') : null; $crid = $this->has_arg('CONTAINERREGISTRYID') ? $this->arg('CONTAINERREGISTRYID') : null; - $pcid = $this->has_arg('PARENTCONTAINERID') ? $this->arg('PARENTCONTAINERID') : null; - $pcl = $this->has_arg('PARENTCONTAINERLOCATION') ? $this->arg('PARENTCONTAINERLOCATION') : null; + $pcid = $this->argIfNotEmptyString('PARENTCONTAINERID'); + $pcl = $this->argIfNotEmptyString('PARENTCONTAINERLOCATION'); $pipeline = $this->has_arg('PROCESSINGPIPELINEID') ? $this->arg('PROCESSINGPIPELINEID') : null; $source = $this->has_arg('SOURCE') ? $this->arg('SOURCE') : null; @@ -2640,7 +2640,7 @@ function _add_container() if ($e->getCode() == 1062) { $this->_error('Barcode is not unique. Please enter a different barcode.', 409); } else { - $this->_error('An unexpected error occurred.', 500); + $this->_error('An unexpected error occurred: ' . $e->getMessage(), 500); } } } @@ -3451,6 +3451,10 @@ function _create_awb() && in_array($this->arg('COUNTRY'), $facility_courier_countries) && Utils::getValueOrDefault($use_shipping_service_redirect_incoming_shipments) ) { + if ($ship['EXTERNALSHIPPINGIDTOSYNCHROTRON']) { + $this->_error("Shipping service error: Booking already exists"); + return; + } try { $this->_create_shipment_shipment_request($ship, $dewars); $this->_output(array('EXTERNAL' => "1")); diff --git a/client/package-lock.json b/client/package-lock.json index 3c41082c6..12a9e713e 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -22,8 +22,6 @@ "d3-scale": "^3.2.3", "d3-scale-chromatic": "^2.0.0", "d3-selection": "^2.0.0", - "date-fns": "^2.16.1", - "date-fns-tz": "^1.0.12", "flot-axislabels": "^1.0.0", "flot-pie": "^1.0.0", "font-awesome": "^4.2.0", @@ -1741,6 +1739,7 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz", "integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==", + "dev": true, "dependencies": { "regenerator-runtime": "^0.13.11" }, @@ -5815,29 +5814,6 @@ "node": ">=12" } }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, - "node_modules/date-fns-tz": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-1.3.8.tgz", - "integrity": "sha512-qwNXUFtMHTTU6CFSFjoJ80W8Fzzp24LntbjFFBgL/faqds4e5mo9mftoRLgr3Vi1trISsg4awSpYVsOQCRnapQ==", - "peerDependencies": { - "date-fns": ">=2.0.0" - } - }, "node_modules/de-indent": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", @@ -14438,7 +14414,8 @@ "node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "dev": true }, "node_modules/regenerator-transform": { "version": "0.15.1", diff --git a/client/package.json b/client/package.json index 4808d17de..befe08a72 100644 --- a/client/package.json +++ b/client/package.json @@ -70,8 +70,6 @@ "d3-scale": "^3.2.3", "d3-scale-chromatic": "^2.0.0", "d3-selection": "^2.0.0", - "date-fns": "^2.16.1", - "date-fns-tz": "^1.0.12", "flot-axislabels": "^1.0.0", "flot-pie": "^1.0.0", "font-awesome": "^4.2.0", diff --git a/client/src/js/models/shipment.js b/client/src/js/models/shipment.js index b55ddc00e..384881b21 100644 --- a/client/src/js/models/shipment.js +++ b/client/src/js/models/shipment.js @@ -11,6 +11,7 @@ define(['backbone'], function (Backbone) { SHIPPINGNAME: { required: true, pattern: 'wwsdash', + msg: 'The Shipment Name is required', }, 'FCODES[]': { @@ -18,8 +19,14 @@ define(['backbone'], function (Backbone) { pattern: 'fcode', }, + SAFETYLEVEL: { + required: true, + msg: 'The Safety Level field is required', + }, + DYNAMIC: { required: true, + msg: 'The Scheduling field is required', }, FIRSTEXPERIMENTID: { @@ -50,10 +57,11 @@ define(['backbone'], function (Backbone) { SENDINGLABCONTACTID: { required: true, + msg: 'The Outgoing Lab Contact field is required', }, RETURNLABCONTACTID: { - required: true, + required: false, }, DELIVERYAGENT_AGENTCODE: { diff --git a/client/src/js/modules/imaging/views/imageviewer.js b/client/src/js/modules/imaging/views/imageviewer.js index 8f39b5c68..6ea6bf3f2 100644 --- a/client/src/js/modules/imaging/views/imageviewer.js +++ b/client/src/js/modules/imaging/views/imageviewer.js @@ -1029,11 +1029,11 @@ define(['marionette', if (options.o.get('DISPENSEX') && options.o.get('DISPENSEY')) { var disx = parseInt(options.o.get('DISPENSEX')) var disy = parseInt(options.o.get('DISPENSEY')) - this.ctx.strokeStyle = 'white' + this.ctx.strokeStyle = 'deeppink' this.ctx.beginPath() this.ctx.arc(disx, disy, 50, 0, 2*Math.PI) this.ctx.stroke() - this.ctx.fillStyle = 'white' + this.ctx.fillStyle = 'deeppink' this.ctx.fillText('D',disx-5*m, disy+5*m) this.ctx.closePath() } diff --git a/client/src/js/modules/shipment/views/container.js b/client/src/js/modules/shipment/views/container.js index fc1031715..755e4a18a 100644 --- a/client/src/js/modules/shipment/views/container.js +++ b/client/src/js/modules/shipment/views/container.js @@ -19,7 +19,6 @@ define(['marionette', 'views/table', 'utils', - 'formatDate', 'utils/editable', 'templates/shipment/container.html'], function(Marionette, Backbone, @@ -40,7 +39,7 @@ define(['marionette', TableView, - utils, formatDate, + utils, Editable, template){ return Marionette.LayoutView.extend({ @@ -186,7 +185,7 @@ define(['marionette', app.alert({ message: 'Container Successfully Queued' }) self.model.set({ CONTAINERQUEUEID: resp.CONTAINERQUEUEID, - QUEUEDTIMESTAMP: formatDate.default(new Date(), 'dd-MM-yyyy HH:mm') + QUEUEDTIMESTAMP: new Date().toLocaleString() }) self.updateAutoCollection() self.sampletable.toggleAuto(true) diff --git a/client/src/js/modules/shipment/views/createawb.js b/client/src/js/modules/shipment/views/createawb.js index 62b3e43b0..9d5373bb9 100644 --- a/client/src/js/modules/shipment/views/createawb.js +++ b/client/src/js/modules/shipment/views/createawb.js @@ -468,6 +468,14 @@ define(['backbone', return } + const ss_url = app.options.get("shipping_service_app_url_incoming") + const externalid = this.shipment.get('EXTERNALSHIPPINGIDTOSYNCHROTRON') + if (externalid && ss_url) { + const link = ss_url+'/shipment-requests/'+externalid+'/incoming' + window.location.assign(link) + return + } + var prod = null if ( ( @@ -510,7 +518,7 @@ define(['backbone', }, success: function(resp) { if ( - app.options.get("shipping_service_app_url_incoming") + ss_url && (Number(self.terms.get('ACCEPTED')) === 1) // terms.ACCEPTED could be undefined, 1, or "1" && app.options.get("facility_courier_countries").includes(country) ) { @@ -521,9 +529,7 @@ define(['backbone', app.alert({message: "Error performing redirect: external shipping id is null"}) return; } - window.location.assign( - `${app.options.get("shipping_service_app_url")}/shipment-requests/${external_id}/incoming` - ) + window.location.assign(`${ss_url}/shipment-requests/${external_id}/incoming`) }) } else { app.message({ message: 'Air Waybill Successfully Created'}) diff --git a/client/src/js/modules/shipment/views/dewarregistry.js b/client/src/js/modules/shipment/views/dewarregistry.js index 806868bf1..e9ee0bd9a 100644 --- a/client/src/js/modules/shipment/views/dewarregistry.js +++ b/client/src/js/modules/shipment/views/dewarregistry.js @@ -6,13 +6,12 @@ define(['marionette', 'backgrid', 'views/form', 'views/filter', 'views/table', 'utils/table', - 'formatDate', 'templates/shipment/dewarregistryadd.html', 'templates/shipment/dewarregistry.html'], function(Marionette, Backgrid, DewarRegistry, DewarProposal, Proposals, LabContacts, FormView, FilterView, - TableView, table, formatDate, addtemplate, template) { + TableView, table, addtemplate, template) { var ClickableRow = table.ClickableRow.extend({ event: 'rdewar:show', @@ -49,7 +48,7 @@ define(['marionette', 'backgrid', this.ui.fc.val('') this.ui.date.val('') this.ui.serial.val('') - this.model.set({ DEWARS: 0, REPORTS: 0, BLTIMESTAMP: formatDate.default(new Date(), 'yyyy-MM-dd HH:mm:ss') }) + this.model.set({ DEWARS: 0, REPORTS: 0, BLTIMESTAMP: new Date().toLocaleString('sv-SE') }) this.trigger('model:saved', this.model) this.setupValidation() }, diff --git a/client/src/js/modules/shipment/views/shipment.js b/client/src/js/modules/shipment/views/shipment.js index 8465c49a5..4e3ea848d 100644 --- a/client/src/js/modules/shipment/views/shipment.js +++ b/client/src/js/modules/shipment/views/shipment.js @@ -49,6 +49,8 @@ define(['marionette', 'click #add_dewar': 'addDewar', 'click a.send': 'sendShipment', 'click a.pdf': utils.signHandler, + 'click a.labels': 'printLabels', + 'click a.awb': 'createAWB', 'click a.cancel_pickup': 'cancelPickup', 'click a.ready': 'markAsReady', }, @@ -61,7 +63,6 @@ define(['marionette', sent: '.sent', booking: '.booking', dhlmessage: '.dhlmessage', - buttons: '.buttons', }, @@ -102,13 +103,31 @@ define(['marionette', }) }, + printLabels: function(e) { + e.preventDefault() + const errors = this.model.validate(this.model.attributes) + if (errors) { + app.alert({ message: 'Cannot print labels: ' + Object.values(errors)[0] }) + } else { + utils.signHandler(e) + } + }, + + createAWB: function(e) { + const errors = this.model.validate(this.model.attributes) + if (errors) { + e.preventDefault() + app.alert({ message: 'Cannot create air waybill: ' + Object.values(errors)[0] }) + } + }, + sendShipment: function(e) { e.preventDefault() var self = this Backbone.ajax({ url: app.apiurl+'/shipment/send/'+this.model.get('SHIPPINGID'), success: function() { - self.model.set({ SHIPPINGSTATUS: 'send to DLS' }) + self.model.set({ SHIPPINGSTATUS: 'sent to facility' }) app.alert({ className: 'message notify', message: 'Shipment successfully marked as sent' }) self.render() }, @@ -209,11 +228,6 @@ define(['marionette', }, showButtons: function() { - if (this.model.get('LCOUT') && this.model.get('SAFETYLEVEL')) { - this.ui.buttons.show() - } else { - this.ui.buttons.hide() - } const status = this.model.get('SHIPPINGSTATUS') const proc = this.model.get('PROCESSING') if ((status === 'opened' || status === 'awb created' || status === 'pickup booked') && proc == 0) { @@ -242,7 +256,7 @@ define(['marionette', this.ui.booking.html(' Create Air Waybill - Disabled') } else if (externalid && ss_url) { const link = ss_url+'/shipment-requests/'+externalid+'/incoming' - this.ui.booking.html(' Manage shipment booking') + this.ui.booking.html(' Manage Shipment Booking') } else { this.ui.booking.html(' Create DHL Air Waybill') } @@ -257,13 +271,12 @@ define(['marionette', const safetylevel = this.model.get('SAFETYLEVEL') const country = this.model.get('COUNTRY') const courier = this.model.get('DELIVERYAGENT_AGENTNAME') - const lcout = this.model.get('LCOUT') const fac_country_nde = app.options.get('facility_courier_countries_nde') const fac_country_link = app.options.get('facility_courier_countries_link') const fac_country = app.options.get('facility_courier_countries') - if (!lcout || !safetylevel) { - this.ui.dhlmessage.html('
') - } else if (label == '1') { + const ss_url = app.options.get("shipping_service_app_url_incoming") + const externalid = this.model.get('EXTERNALSHIPPINGIDTOSYNCHROTRON') + if (label == '1') { this.ui.dhlmessage.html('') } else if (safetylevel && safetylevel == "Red") { this.ui.dhlmessage.html('') @@ -273,6 +286,8 @@ define(['marionette', this.ui.dhlmessage.html('') } else if (courier && courier.toLowerCase().trim() != 'dhl') { this.ui.dhlmessage.html('') + } else if (externalid && ss_url) { + this.ui.dhlmessage.html('') } else { this.ui.dhlmessage.html('') } diff --git a/client/src/js/modules/stats/views/breakdown.js b/client/src/js/modules/stats/views/breakdown.js index 4a29a2f5d..dc2e055b5 100644 --- a/client/src/js/modules/stats/views/breakdown.js +++ b/client/src/js/modules/stats/views/breakdown.js @@ -1,12 +1,11 @@ define(['marionette', 'templates/stats/breakdown.html', 'utils', - 'formatDate', 'jquery', 'jquery.flot', 'jquery.flot.time', 'jquery.flot.selection', 'jquery.flot.tooltip', - ], function(Marionette, template, utils, formatDate, $) { + ], function(Marionette, template, utils, $) { return Marionette.ItemView.extend({ template: template, @@ -101,8 +100,8 @@ define(['marionette', 'templates/stats/breakdown.html', if (this.hideOverview) return var opts = this.main.getOptions() - var from = formatDate.default(opts.xaxes[0].min, 'MMMM do yyyy') - var to = formatDate.default(opts.xaxes[0].max, 'MMMM do yyyy') + var from = new Date(opts.xaxes[0].min).toLocaleDateString(); + var to = new Date(opts.xaxes[0].max).toLocaleDateString(); if (from != to) this.ui.span.text(from+' - '+to) else this.ui.span.text(from) diff --git a/client/src/js/modules/types/mx/shipment/views/mx-container-add.vue b/client/src/js/modules/types/mx/shipment/views/mx-container-add.vue index 6c60d3878..c2875533a 100644 --- a/client/src/js/modules/types/mx/shipment/views/mx-container-add.vue +++ b/client/src/js/modules/types/mx/shipment/views/mx-container-add.vue @@ -751,8 +751,8 @@ export default { this.NAME = '' this.BARCODE = '' this.CONTAINERREGISTRYID = '' - this.PARENTCONTAINERID = '' - this.PARENTCONTAINERLOCATION = '' + this.PARENTCONTAINERID = null + this.PARENTCONTAINERLOCATION = null // Trigger default setting of UDC fields if selected this.selectQueueForUDC(this.AUTOMATED) diff --git a/client/src/js/modules/types/mx/shipment/views/mx-container-view.vue b/client/src/js/modules/types/mx/shipment/views/mx-container-view.vue index 9a24cd7fb..cf62bd2b5 100644 --- a/client/src/js/modules/types/mx/shipment/views/mx-container-view.vue +++ b/client/src/js/modules/types/mx/shipment/views/mx-container-view.vue @@ -288,7 +288,6 @@