diff --git a/CHANGES.rst b/CHANGES.rst index 36f6409034..8c5c1dd4c8 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -46,6 +46,7 @@ Changelog **Removed** +- #1531 Remove sampling rounds from core - #1551 Removed dependency to plone.app.iterate - #1530 Removed ARImport - #1530 Removed stale type registrations diff --git a/bika/lims/__init__.py b/bika/lims/__init__.py index 14815547ae..e2d227abad 100644 --- a/bika/lims/__init__.py +++ b/bika/lims/__init__.py @@ -126,7 +126,6 @@ def initialize(context): from content.samplepoint import SamplePoint # noqa from content.sampletype import SampleType # noqa from content.samplingdeviation import SamplingDeviation # noqa - from content.srtemplate import SRTemplate # noqa from content.storagelocation import StorageLocation # noqa from content.subgroup import SubGroup # noqa from content.supplier import Supplier # noqa @@ -164,7 +163,6 @@ def initialize(context): from controlpanel.bika_samplepoints import SamplePoints # noqa from controlpanel.bika_sampletypes import SampleTypes # noqa from controlpanel.bika_samplingdeviations import SamplingDeviations # noqa - from controlpanel.bika_srtemplates import SRTemplates # noqa from controlpanel.bika_storagelocations import StorageLocations # noqa from controlpanel.bika_subgroups import SubGroups # noqa from controlpanel.bika_suppliers import Suppliers # noqa diff --git a/bika/lims/adapters/widgetvisibility.py b/bika/lims/adapters/widgetvisibility.py index 255fd438a9..d94f65e34a 100644 --- a/bika/lims/adapters/widgetvisibility.py +++ b/bika/lims/adapters/widgetvisibility.py @@ -132,7 +132,7 @@ class ScheduledSamplingFieldsVisibility(SenaiteATWidgetVisibility): def __init__(self, context): super(ScheduledSamplingFieldsVisibility, self).__init__( context=context, sort=10, - field_names=["ScheduledSamplingSampler", "SamplingRound"]) + field_names=["ScheduledSamplingSampler"]) def isVisible(self, field, mode="view", default="visible"): if not self.context.bika_setup.getScheduleSamplingEnabled(): diff --git a/bika/lims/browser/analysisrequest/add2.py b/bika/lims/browser/analysisrequest/add2.py index 8367c2a11d..f9c4185fc0 100644 --- a/bika/lims/browser/analysisrequest/add2.py +++ b/bika/lims/browser/analysisrequest/add2.py @@ -855,9 +855,6 @@ def get_client_info(self, obj): "Specification": { "getClientUID": [uid, ""], }, - "SamplingRound": { - "getParentUID": [uid], - }, "Sample": { "getClientUID": [uid], }, diff --git a/bika/lims/browser/client/__init__.py b/bika/lims/browser/client/__init__.py index 03bc80b542..8559819301 100644 --- a/bika/lims/browser/client/__init__.py +++ b/bika/lims/browser/client/__init__.py @@ -22,11 +22,9 @@ from views.analysisrequests import ClientAnalysisRequestsView from views.analysisprofiles import ClientAnalysisProfilesView from views.artemplates import ClientARTemplatesView -from views.srtemplates import ClientSamplingRoundTemplatesView from views.samplepoints import ClientSamplePointsView from views.analysisspecs import ClientAnalysisSpecsView from views.attachments import ClientAttachmentsView from views.orders import ClientOrdersView from views.contacts import ClientContactsView from views.contacts import ClientContactVocabularyFactory -from views.samplingrounds import ClientSamplingRoundsView diff --git a/bika/lims/browser/client/configure.zcml b/bika/lims/browser/client/configure.zcml index 3edad7d5d4..88ad63ce32 100644 --- a/bika/lims/browser/client/configure.zcml +++ b/bika/lims/browser/client/configure.zcml @@ -43,14 +43,6 @@ layer="bika.lims.interfaces.IBikaLIMS" /> - - - - diff --git a/bika/lims/browser/client/views/samplingrounds.py b/bika/lims/browser/client/views/samplingrounds.py deleted file mode 100644 index e65de349bc..0000000000 --- a/bika/lims/browser/client/views/samplingrounds.py +++ /dev/null @@ -1,47 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of SENAITE.CORE. -# -# SENAITE.CORE is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright 2018-2020 by it's authors. -# Some rights reserved, see README and LICENSE. - -from Products.CMFCore.utils import getToolByName -from bika.lims import bikaMessageFactory as _ -from bika.lims.controlpanel.bika_samplingrounds import SamplingRoundsView - - -class ClientSamplingRoundsView(SamplingRoundsView): - """This is displayed in the "Sampling Rounds" tab on each client - """ - - def __init__(self, context, request): - super(ClientSamplingRoundsView, self).__init__(context, request) - self.contentFilter = { - 'portal_type': 'SamplingRound', - 'sort_on': 'sortable_title', - 'path': { - "query": "/".join(self.context.getPhysicalPath()), - "level": 0}, - } - self.title = self.context.translate(_("Client Sampling Rounds")) - self.context_actions = { - _('Add'): {'url': '++add++SamplingRound', # To work with dexterity - 'permission': 'Add portal content', - 'icon': '++resource++bika.lims.images/add.png'}} - - def __call__(self): - mtool = getToolByName(self.context, 'portal_membership') - return super(ClientSamplingRoundsView, self).__call__() diff --git a/bika/lims/browser/client/views/srtemplates.py b/bika/lims/browser/client/views/srtemplates.py deleted file mode 100644 index 3ca1ae8a1f..0000000000 --- a/bika/lims/browser/client/views/srtemplates.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of SENAITE.CORE. -# -# SENAITE.CORE is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright 2018-2020 by it's authors. -# Some rights reserved, see README and LICENSE. - -from bika.lims.controlpanel.bika_srtemplates import SamplingRoundTemplatesView - - -class ClientSamplingRoundTemplatesView(SamplingRoundTemplatesView): - """ - Displays the client-specific Sampling Round Templates. - """ - - def __init__(self, context, request): - super(ClientSamplingRoundTemplatesView, self).__init__(context, request) diff --git a/bika/lims/browser/configure.zcml b/bika/lims/browser/configure.zcml index 26a222aac9..2a9148364c 100644 --- a/bika/lims/browser/configure.zcml +++ b/bika/lims/browser/configure.zcml @@ -48,8 +48,6 @@ - - diff --git a/bika/lims/browser/images/srtemplate.png b/bika/lims/browser/images/srtemplate.png deleted file mode 100644 index 9ee64c26c5..0000000000 Binary files a/bika/lims/browser/images/srtemplate.png and /dev/null differ diff --git a/bika/lims/browser/images/srtemplate_big.png b/bika/lims/browser/images/srtemplate_big.png deleted file mode 100644 index 7ad8601dbd..0000000000 Binary files a/bika/lims/browser/images/srtemplate_big.png and /dev/null differ diff --git a/bika/lims/browser/js/bika.lims.loader.js b/bika/lims/browser/js/bika.lims.loader.js index e650b05f31..28bda70961 100644 --- a/bika/lims/browser/js/bika.lims.loader.js +++ b/bika/lims/browser/js/bika.lims.loader.js @@ -72,14 +72,6 @@ window.bika.lims.controllers = { "div.overlay #client-base-edit": ['ClientOverlayHandler'], - // Client Sampling Rounds - ".template-bika-lims-content-samplingsround.portaltype-client": - ['ClientSamplingRoundAddEditView'], - - // Sampling Rounds PrintView - "#sr_publish_container": - ['SamplingRoundPrintView'], - // Reference Samples ".portaltype-referencesample.template-analyses": ['ReferenceSampleAnalysesView'], diff --git a/bika/lims/browser/js/bika.lims.samplinground.print.js b/bika/lims/browser/js/bika.lims.samplinground.print.js deleted file mode 100644 index 87b26a635a..0000000000 --- a/bika/lims/browser/js/bika.lims.samplinground.print.js +++ /dev/null @@ -1,379 +0,0 @@ -/** - * Controller class for SamplingRound Print View - */ -function SamplingRoundPrintView() { - - var that = this; - var referrer_cookie_name = '_srpv'; - - // Allowed Paper sizes and default margins, in mm - var papersize_default = "A4"; - var default_margins = [20, 20, 20, 20]; - var papersize = { - 'A4': { - dimensions: [210, 297], - margins: [20, 20, 20, 20] }, - - 'letter': { - dimensions: [215.9, 279.4], - margins: [20, 20, 20, 20] }, - }; - - /** - * Entry-point method for AnalysisRequestPublishView - */ - that.load = function() { - - // The report will be loaded dynamically by reloadReport() - $('#report').html('').hide(); - - // Load the report - reloadReport(); - - // Store referrer in cookie in case it is lost due to a page reload - var cookiename = "sr.publish.view.referrer"; - var backurl = document.referrer; - if (backurl) { - createCookie(cookiename, backurl); - } else { - backurl = readCookie(cookiename); - // Fallback to portal_url instead of staying inside publish. - if (!backurl) { - backurl = portal_url; - } - } - - $('#sel_format').change(function(e) { - reloadReport(); - }); - - $('#sel_layout').change(function(e) { - $('body').removeClass($('body').attr('data-layout')); - $('body').attr('data-layout', $(this).val()); - $('body').addClass($(this).val()); - reloadReport(); - }); - - $('#cancel_button').click(function(e) { - location.href=backurl; - }); - $('#print_button').click(function(e) { - e.preventDefault(); - var url = window.location.href; - $('#sr_publish_container').animate({opacity:0.4}, 'slow'); - var count = $('#sr_publish_container #report .report_body').length; - $('#sr_publish_container #report .report_body').each(function(){ - var rephtml = $(this).clone().wrap('
').parent().html(); - var repstyle = $('#report-style').clone().wrap('
').parent().html(); - repstyle += $('#layout-style').clone().wrap('
').parent().html(); - var form='
' + - '' + - '' + - '' + - '
'; - $('body').html(form); - document.forms.form.submit(); - }); - }); - }; - - function get(name){ - if(name=(new RegExp('[?&]'+encodeURIComponent(name)+'=([^&]*)')).exec(location.search)) - return decodeURIComponent(name[1]); - } - - function load_barcodes() { - // Barcode generator - $('.barcode').each(function() { - var id = $(this).attr('data-id'); - var code = $(this).attr('data-code'); - var barHeight = $(this).attr('data-barHeight'); - var addQuietZone = $(this).attr('data-addQuietZone'); - var showHRI = $(this).attr('data-showHRI'); - $(this).barcode(id, code, - {'barHeight': parseInt(barHeight), - 'addQuietZone': Boolean(addQuietZone), - 'showHRI': Boolean(showHRI) }); - }); - } - - function convert_svgs() { - $('svg').each(function(e) { - var svg = $("
").append($(this).clone()).html(); - var img = window.bika.lims.CommonUtils.svgToImage(svg); - $(this).replaceWith(img); - }); - } - - /** - * Re-load the report view in accordance to the values set in the - * options panel (report format, pagesize, QC visible, etc.) - */ - function reloadReport() { - var url = window.location.href; - var template = $('#sel_format').val(); - if ($('#report:visible').length > 0) { - $('#report').fadeTo('fast', 0.4); - } - $.ajax({ - url: url, - type: 'POST', - async: true, - data: { "template": template} - }) - .always(function(data) { - var htmldata = data; - cssdata = $(htmldata).find('#report-style').html(); - $('#report-style').html(cssdata); - htmldata = $(htmldata).find('#report').html(); - $('#report').html(htmldata); - $('#report').fadeTo('fast', 1); - load_barcodes(); - load_layout(); - convert_svgs(); - }); - } - - /** - * Applies the selected layout (A4, US-letter) to the reports view, - * splits each report in pages depending on the layout and margins - * and applies the dynamic footer and/or header if required. - * In fact, this method makes the html ready to be printed via - * Weasyprint. - */ - function load_layout() { - // Set page layout (DIN-A4, US-letter, etc.) - var currentlayout = $('#sel_layout').val(); - // Dimensions. All expressed in mm - var dim = { - size: papersize[currentlayout].size, - outerWidth: papersize[currentlayout].dimensions[0], - outerHeight: papersize[currentlayout].dimensions[1], - marginTop: papersize[currentlayout].margins[0], - marginRight: papersize[currentlayout].margins[1], - marginBottom: papersize[currentlayout].margins[2], - marginLeft: papersize[currentlayout].margins[3], - width: papersize[currentlayout].dimensions[0]-papersize[currentlayout].margins[1]-papersize[currentlayout].margins[3], - height: papersize[currentlayout].dimensions[1]-papersize[currentlayout].margins[0]-papersize[currentlayout].margins[2] - }; - - var layout_style = - '@page { size: ' + dim.size + ' !important;' + - ' width: ' + dim.width + 'mm !important;' + - ' margin: 0mm '+dim.marginRight+'mm 0mm '+dim.marginLeft+'mm !important;'; - $('#layout-style').html(layout_style); - $('#sr_publish_container').css({'width':dim.width + 'mm', 'padding': '0mm '+dim.marginRight + 'mm 0mm '+dim.marginLeft +'mm '}); - $('#sr_publish_header').css('margin', '0mm -'+dim.marginRight + 'mm 0mm -' +dim.marginLeft+'mm'); - $('div.report_body').css({'width': dim.width + 'mm', 'max-width': dim.width + 'mm', 'min-width': dim.width + 'mm'}); - - // Iterate for each AR report and apply the dimensions, header, - // footer, etc. - $('div.report_body').each(function(i) { - - var arbody = $(this); - - // Header defined for this AR Report? - // Note that if the header of the report is taller than the - // margin, the header will be dismissed. - var header_html = ''; - var header_height = $(header_html).outerHeight(true); - if ($(this).find('.page-header').length > 0) { - var pgh = $(this).find('.page-header').first(); - header_height = parseFloat($(pgh).outerHeight(true)); - if (header_height > mmTopx(dim.marginTop)) { - // Footer too tall - header_html = ""; - header_height = parseFloat($(header_html)); - } else { - header_html = ''; - } - $(this).find('.page-header').remove(); - } - - // Footer defined for this AR Report? - // Note that if the footer of the report is taller than the - // margin, the footer will be dismissed - var footer_html = ''; - var footer_height = $(footer_html).outerHeight(true); - if ($(this).find('.page-footer').length > 0) { - var pgf = $(this).find('.page-footer').first(); - footer_height = parseFloat($(pgf).outerHeight(true)); - if (footer_height > mmTopx(dim.marginBottom)) { - // Footer too tall - footer_html = ""; - footer_height = parseFloat($(footer_html)); - } else { - footer_html = ''; - } - $(this).find('.page-footer').remove(); - } - - // Remove undesired and orphan page breaks - $(this).find('.page-break').remove(); - if ($(this).find('div').last().hasClass('manual-page-break')) { - $(this).find('div').last().remove(); - } - if ($(this).find('div').first().hasClass('manual-page-break')) { - $(this).find('div').first().remove(); - } - - // Top offset by default. The position in which the report - // starts relative to the top of the window. Used later to - // calculate when a page-break is needed. - var topOffset = $(this).position().top; - var maxHeight = mmTopx(dim.height); - var elCurrent = null; - var elOutHeight = 0; - var contentHeight = 0; - var pagenum = 1; - var pagecounts = Array(); - - // Iterate through all div children to find the suitable - // page-break points, split the report and add the header - // and footer as well as pagination count as required. - // - // IMPORTANT - // Please note that only first-level div elements from - // within div.ar_publish_body are checked and will be - // treated as nob-breakable elements. So, if a div element - // from within a div.ar_publish_body is taller than the - // maximum allowed height, that element will be omitted. - // Further improvements may solve this and handle deeply - // elements from the document, such as tables, etc. Other - // elements could be then labeled with "no-break" class to - // prevent the system to break them. - //console.log("OFF\tABS\tREL\tOUT\tHEI\tMAX"); - $(this).children('div:visible').each(function(z) { - - // Is the first page? - if (elCurrent === null) { - // Add page header if required - $(header_html).insertBefore($(this)); - topOffset = $(this).position().top; - } - - // Instead of using the height css of each element to - // know if the total height at this iteration is above - // the maximum health, we use the element's position. - // This way, we will prevent underestimations due - // non-div elements or plain text directly set inside - // the div.ar_publish_body container, not wrapped by - // other div element. - var elAbsTopPos = $(this).position().top; - var elRelTopPos = elAbsTopPos - topOffset; - var elNext = $(this).next(); - elOutHeight = parseFloat($(this).outerHeight(true)); - if ($(elNext).length > 0) { - // Calculate the height of the element according to - // the position of the next element instead of - // using the outerHeight. - elOutHeight = $(elNext).position().top-elAbsTopPos; - } - - // The current element is taller than the maximum? - if (elOutHeight > maxHeight) { - console.warn("Element with id "+$(this).attr('id')+ - " has a height above the maximum: "+ - elOutHeight); - } - - // Accumulated height - contentHeight = elRelTopPos + elOutHeight; - /*console.log(Math.floor(topOffset) + "\t" + - Math.floor(elAbsTopPos) + "\t" + - Math.floor(elRelTopPos) + "\t" + - Math.floor(elOutHeight) + "\t" + - Math.floor(contentHeight) + "\t" + - Math.floor(maxHeight) + "\t" + - '#'+$(this).attr('id')+"."+$(this).attr('class'));*/ - - if (contentHeight > maxHeight || - $(this).hasClass('manual-page-break')) { - // The content is taller than the allowed height - // or a manual page break reached. Add a page break. - var paddingTopFoot = maxHeight - elRelTopPos; - var manualbreak = $(this).hasClass('manual-page-break'); - var restartcount = manualbreak && $(this).hasClass('restart-page-count'); - var aboveBreakHtml = "
"; - var pageBreak = "
"; - $(aboveBreakHtml + footer_html + pageBreak + header_html).insertBefore($(this)); - topOffset = $(this).position().top; - if (manualbreak) { - $(this).hide(); - if (restartcount) { - // The page count needs to be restarted! - pagecounts.push(pagenum); - pagenum = 0; - } - } - contentHeight = $(this).outerHeight(true); - pagenum += 1; - } - $(this).css('width', '100%'); - elCurrent = $(this); - }); - - // Document end-footer - if (elCurrent !== null) { - var paddingTopFoot = maxHeight - contentHeight; - var aboveBreakHtml = "
"; - var pageBreak = "
"; - pagecounts.push(pagenum); - $(aboveBreakHtml + footer_html + pageBreak).insertAfter($(elCurrent)); - } - - // Wrap all elements in pages - var split_at = 'div.page-header'; - $(this).find(split_at).each(function() { - $(this).add($(this).nextUntil(split_at)).wrapAll("
"); - }); - - // Move headers and footers out of the wrapping and assign - // the top and bottom margins - $(this).find('div.page-header').each(function() { - var baseheight = $(this).height(); - $(this).css({'height': pxTomm(baseheight)+"mm", - 'margin': 0, - 'padding': (pxTomm(mmTopx(dim.marginTop) - baseheight)+"mm 0 0 0")}); - $(this).parent().before(this); - }); - $(this).find('div.page-break').each(function() { - $(this).parent().after(this); - }); - $(this).find('div.page-footer').each(function() { - $(this).css({'height': dim.marginBottom+"mm", - 'margin': 0, - 'padding': 0}); - $(this).parent().after(this); - }); - - // Page numbering - pagenum = 1; - var pagecntidx = 0; - $(this).find('.page-current-num,.page-total-count,div.page-break').each(function() { - if ($(this).hasClass('page-break')) { - if ($(this).hasClass('restart-page-count')) { - pagenum = 1; - pagecntidx += 1; - } else { - pagenum = parseInt($(this).attr('data-pagenum')) + 1; - } - } else if ($(this).hasClass('page-current-num')) { - $(this).html(pagenum); - } else { - $(this).html(pagecounts[pagecntidx]); - } - }); - }); - // Remove manual page breaks - $('.manual-page-break').remove(); - } -} -var mmTopx = function(mm) { - var px = parseFloat(mm*$('#my_mm').height()); - return px > 0 ? Math.ceil(px) : Math.floor(px); -}; -var pxTomm = function(px){ - var mm = parseFloat(px/$('#my_mm').height()); - return mm > 0 ? Math.floor(mm) : Math.ceil(mm); -}; diff --git a/bika/lims/browser/js/bika.lims.samplingrounds.js b/bika/lims/browser/js/bika.lims.samplingrounds.js deleted file mode 100644 index c9291b6f03..0000000000 --- a/bika/lims/browser/js/bika.lims.samplingrounds.js +++ /dev/null @@ -1,116 +0,0 @@ -/** - * Controller class for Client's sampling round Add/Edit view - */ -function ClientSamplingRoundAddEditView() { - - var that = this; - - /** - * Entry-point method for ClientSamplingRoundAddEditView - */ - that.load = function() { - /** - * Allow to fill out the fields manually or automatically by selecting a Sampling Round Template (ReferenceField). - */ - $('select#form-widgets-sr_template') - .bind('click', function () { - if (hasSamplingRoundTemplateData()) { - setSamplingRoundTemplateData(); - } - else { - unsetSamplingRoundTemplate(); - } - }); - // Hiding not needed buttons - $("button[name='upButton']").hide(); - $("button[name='downButton']").hide(); - }; - - function hasSamplingRoundTemplateData() { - /** - * Checks if the sampling rounds template field has a sampling rounds template selected. - * :returns: True if the field has data and False if the field contains "--NOVALUE--" - */ - var value = $('select#form-widgets-sr_template').val(); - return value != "--NOVALUE--"; - } - - function setSamplingRoundTemplateData() { - /** - * This function gets the Sampling Rounds Template information and fill out each field. - * The function also binds an event to each filled field in order to unset the Sampling Round Template - * if one of the fields change. - */ - - // Getting the Sampling Round Template's data - var srt_uid = $('select#form-widgets-sr_template').val(); - if (srt_uid === undefined || srt_uid === null){ - srt_uid=''; - } - var sampler, department, samp_freq, instructions, artemplates_uids; - var request_data = { - catalog_name: "portal_catalog", - UID: srt_uid, - content_type: 'SRTemplate' - }; - window.bika.lims.jsonapi_read(request_data, function (data) { - if (data.objects && data.objects.length > 0) { - var ob = data.objects[0]; - sampler = ob['Sampler']; - department = ob['Department_uid']; - samp_freq = ob['SamplingDaysFrequency']; - instructions = ob['Instructions']; - artemplates_uids = ob['ARTemplates_uid']; - } - // Writing the Sampling Round Template's data - $("select#form-widgets-sampler").val(sampler); - $("select#form-widgets-department").val(department); - $("input#form-widgets-sampling_freq").val(samp_freq); - $("textarea#form-widgets-instructions").val(instructions); - // Setting Analysis Request Template - // Moving all options contained in "to" box to the "from" box - var to_options = $("select#form-widgets-model-to option"); - if(to_options.length >=1) { - to_options.each(function () { - $(this).click(); - }); - $("button[name='to2fromButton']").click(); // Trigger the widget JS - } - if (artemplates_uids) { - for (var i = 0; i <= artemplates_uids.length; i++) { - $("option[value='" + artemplates_uids[i] + "']").attr('selected', 'selected'); - } - } - if(artemplates_uids.length > 0) { - $("button[name='from2toButton']").click(); // Trigger the widget JS - } - }); - // Binding the unsetSamplingRoundsTemplate function - $("select#form-widgets-sampler," + - "select#form-widgets-department," + - "input#form-widgets-sampling_freq," + - "textarea#form-widgets-instructions") - .bind('change copy selected', function () { - unsetSamplingRoundTemplate(); - }); - $("button[name='to2fromButton'], button[name='from2toButton']") - .bind('blur', function () { - unsetSamplingRoundTemplate(); - }); - } - - function unsetSamplingRoundTemplate(){ - /** - This function disables the selected sampling Round Template and cut all bindings done in - setSamplingRoundTemplate(). - */ - $('select#form-widgets-sr_template').val("--NOVALUE--"); - $("select#form-widgets-sampler," + - "select#form-widgets-department," + - "input#form-widgets-sampling_freq," + - "textarea#form-widgets-instructions," + - "textarea#form-widgets-instructions," + - "button[name='to2fromButton']," + - "button[name='from2toButton']").unbind(); - } -} diff --git a/bika/lims/browser/samplinground/__init__.py b/bika/lims/browser/samplinground/__init__.py deleted file mode 100644 index b54d2c0984..0000000000 --- a/bika/lims/browser/samplinground/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of SENAITE.CORE. -# -# SENAITE.CORE is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright 2018-2020 by it's authors. -# Some rights reserved, see README and LICENSE. diff --git a/bika/lims/browser/samplinground/add.py b/bika/lims/browser/samplinground/add.py deleted file mode 100644 index 2f42aa5652..0000000000 --- a/bika/lims/browser/samplinground/add.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of SENAITE.CORE. -# -# SENAITE.CORE is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright 2018-2020 by it's authors. -# Some rights reserved, see README and LICENSE. - -from plone.dexterity.browser import add -from AccessControl import Unauthorized - -class AddForm(add.DefaultAddForm): - """ - This class is made to check the add form permissions against client's contact users - """ - def __call__(self): - # Checking current user permissions - if self.context.hasUserAddEditPermission(): - return add.DefaultAddForm.__call__(self) - else: - raise Unauthorized diff --git a/bika/lims/browser/samplinground/analysisrequests.py b/bika/lims/browser/samplinground/analysisrequests.py deleted file mode 100644 index ffa24f1c29..0000000000 --- a/bika/lims/browser/samplinground/analysisrequests.py +++ /dev/null @@ -1,267 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of SENAITE.CORE. -# -# SENAITE.CORE is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright 2018-2020 by it's authors. -# Some rights reserved, see README and LICENSE. - -from bika.lims import bikaMessageFactory as _ -from bika.lims.browser.analysisrequest import AnalysisRequestAddView as _ARAV -from bika.lims.browser.analysisrequest import AnalysisRequestsView as _ARV -from bika.lims.permissions import * -from plone.app.layout.globals.interfaces import IViewView -from Products.CMFCore.utils import getToolByName -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile -from zope.interface import implements -from bika.lims.utils import t -from copy import copy - - -class AnalysisRequestsView(_ARV, _ARAV): - implements(IViewView) - - def __init__(self, context, request): - super(AnalysisRequestsView, self).__init__(context, request) - self.catalog = "portal_catalog" - SamplingWorkflowEnabled = self.context.bika_setup.getSamplingWorkflowEnabled() - self.columns = { - 'securitySealIntact': {'title': _('Security Seal Intact'), - 'toggle': True}, - 'samplingRoundTemplate': {'title': _('Sampling Round Template'), - 'toggle': True}, - 'getId': {'title': _('Request ID'), - 'index': 'getId'}, - 'getDateSampled': {'title': _('Date Sampled'), - 'index': 'getDateSampled', - 'toggle': True, - 'input_class': 'datetimepicker', - 'input_width': '10'}, - 'state_title': {'title': _('State'), - 'index': 'review_state'}, - 'getProfilesTitle': {'title': _('Profile'), - 'toggle': False}, - 'getTemplateTitle': {'title': _('Template'), - 'toggle': False}, - } - - self.review_states = [ - {'id': 'default', - 'title': _('Active'), - 'contentFilter': {'is_active': True, - 'sort_on': 'created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'sample'}, - {'id': 'preserve'}, - {'id': 'receive'}, - {'id': 'retract'}, - {'id': 'verify'}, - {'id': 'prepublish'}, - {'id': 'publish'}, - {'id': 'republish'}, - {'id': 'cancel'}, - {'id': 'reinstate'}], - 'custom_transitions': [], - 'columns': ['securitySealIntact', - 'getId', - 'samplingRoundTemplate', - 'getDateSampled', - 'state_title']}, - {'id': 'sample_due', - 'title': _('Due'), - 'contentFilter': {'review_state': ('to_be_sampled', - 'to_be_preserved', - 'sample_due'), - 'sort_on': 'created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'sample'}, - {'id': 'preserve'}, - {'id': 'receive'}, - {'id': 'cancel'}, - {'id': 'reinstate'}], - 'custom_transitions': [], - 'columns': ['securitySealIntact', - 'getId', - 'samplingRoundTemplate', - 'getDateSampled', - 'state_title']}, - {'id': 'sample_received', - 'title': _('Received'), - 'contentFilter': {'review_state': 'sample_received', - 'sort_on': 'created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'prepublish'}, - {'id': 'cancel'}, - {'id': 'reinstate'}], - 'custom_transitions': [], - 'columns': ['securitySealIntact', - 'getId', - 'samplingRoundTemplate', - 'getDateSampled', - 'state_title']}, - {'id': 'to_be_verified', - 'title': _('To be verified'), - 'contentFilter': {'review_state': 'to_be_verified', - 'sort_on': 'created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'retract'}, - {'id': 'verify'}, - {'id': 'prepublish'}, - {'id': 'cancel'}, - {'id': 'reinstate'}], - 'custom_transitions': [], - 'columns': ['securitySealIntact', - 'getId', - 'samplingRoundTemplate', - 'getDateSampled', - 'state_title']}, - {'id': 'verified', - 'title': _('Verified'), - 'contentFilter': {'review_state': 'verified', - 'sort_on': 'created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'publish'}], - 'custom_transitions': [], - 'columns': ['securitySealIntact', - 'getId', - 'samplingRoundTemplate', - 'getDateSampled', - 'state_title']}, - {'id': 'published', - 'title': _('Published'), - 'contentFilter': {'review_state': ('published', 'invalid'), - 'sort_on': 'created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'republish'}], - 'custom_transitions': [], - 'columns': ['securitySealIntact', - 'getId', - 'samplingRoundTemplate', - 'getDateSampled', - 'state_title']}, - {'id': 'cancelled', - 'title': _('Cancelled'), - 'contentFilter': {'is_active': False, - 'sort_on': 'created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'reinstate'}], - 'custom_transitions': [], - 'columns': ['securitySealIntact', - 'getId', - 'samplingRoundTemplate', - 'getDateSampled', - 'state_title']}, - {'id': 'invalid', - 'title': _('Invalid'), - 'contentFilter': {'review_state': 'invalid', - 'sort_on': 'created', - 'sort_order': 'reverse'}, - 'transitions': [], - 'custom_transitions': [], - 'columns': ['securitySealIntact', - 'getId', - 'samplingRoundTemplate', - 'getDateSampled', - 'state_title']}, - {'id': 'assigned', - 'title': "" % ( - t(_("Assigned")), self.portal_url), - 'contentFilter': {'assigned_state': 'assigned', - 'review_state': ('sample_received', 'to_be_verified', - 'attachment_due', 'verified', - 'published'), - 'sort_on': 'created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'retract'}, - {'id': 'verify'}, - {'id': 'prepublish'}, - {'id': 'publish'}, - {'id': 'republish'}, - {'id': 'cancel'}, - {'id': 'reinstate'}], - 'custom_transitions': [], - 'columns': ['securitySealIntact', - 'getId', - 'samplingRoundTemplate', - 'getDateSampled', - 'state_title']}, - {'id': 'unassigned', - 'title': "" % ( - t(_("Unassigned")), self.portal_url), - 'contentFilter': {'assigned_state': 'unassigned', - 'review_state': ('sample_received', 'to_be_verified', - 'attachment_due', 'verified', - 'published'), - 'sort_on': 'created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'receive'}, - {'id': 'retract'}, - {'id': 'verify'}, - {'id': 'prepublish'}, - {'id': 'publish'}, - {'id': 'republish'}, - {'id': 'cancel'}, - {'id': 'reinstate'}], - 'custom_transitions': [], - 'columns': ['securitySealIntact', - 'getId', - 'samplingRoundTemplate', - 'getDateSampled', - 'state_title']}, - ] - - def contentsMethod(self, contentFilter): - pc = getToolByName(self.context, 'portal_catalog') - if 'SamplingRoundUID' not in contentFilter.keys(): - contentFilter['SamplingRoundUID'] = self.context.UID() - return pc(contentFilter) - - def __call__(self): - self.context_actions = {} - mtool = getToolByName(self.context, 'portal_membership') - if mtool.checkPermission(AddAnalysisRequest, self.portal): - # We give the number of analysis request templates in order to fill out the analysis request form - # automatically :) - num_art = len(self.context.ar_templates) - self.context_actions[self.context.translate(_('Add new'))] = { - 'url': self.context.aq_parent.absolute_url() + \ - "/portal_factory/" - "AnalysisRequest/Request new analyses/ar_add?samplinground=" - + self.context.UID() + "&ar_count=" + str(num_art), - 'icon': '++resource++bika.lims.images/add.png'} - return super(AnalysisRequestsView, self).__call__() - - def folderitem(self, obj, item, index): - # Call the folderitem method from the base class - item = _ARV.folderitem(self, obj, item, index) - # In sampling rounds, analysis request list will be listed per Sample - # Partition/Container Obtaining analysis requests - # TODO-performance: don't get the full object - obj = obj.getObject() - # Getting the sampling round template uid - srTemplateUID = obj.getSamplingRound().sr_template if obj.getSamplingRound().sr_template else '' - # Getting the sampling round object - catalog = getToolByName(self.context, 'uid_catalog') - srTemplateObj = catalog(UID=srTemplateUID)[0].getObject() if catalog(UID=srTemplateUID) else None - item['samplingRoundTemplate'] = '' - if srTemplateObj: - item['samplingRoundTemplate'] = srTemplateObj.title - item['replace']['samplingRoundTemplate'] = \ - "%s" % ( - srTemplateObj.absolute_url, item['samplingRoundTemplate']) - item['securitySealIntact'] = '' - return item diff --git a/bika/lims/browser/samplinground/configure.zcml b/bika/lims/browser/samplinground/configure.zcml deleted file mode 100644 index bb2ca73b03..0000000000 --- a/bika/lims/browser/samplinground/configure.zcml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - diff --git a/bika/lims/browser/samplinground/edit.py b/bika/lims/browser/samplinground/edit.py deleted file mode 100644 index e2b1ff3d60..0000000000 --- a/bika/lims/browser/samplinground/edit.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of SENAITE.CORE. -# -# SENAITE.CORE is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright 2018-2020 by it's authors. -# Some rights reserved, see README and LICENSE. - -from plone.dexterity.browser import edit -from AccessControl import Unauthorized - -class EditForm(edit.DefaultEditForm): - """ - This class is made to check the edit form permissions against client's contact users - """ - def __call__(self): - # Checking current user permissions - if self.context.hasUserAddEditPermission(): - return edit.DefaultEditForm.__call__(self) - else: - raise Unauthorized diff --git a/bika/lims/browser/samplinground/printform.py b/bika/lims/browser/samplinground/printform.py deleted file mode 100644 index bf68dfde21..0000000000 --- a/bika/lims/browser/samplinground/printform.py +++ /dev/null @@ -1,265 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of SENAITE.CORE. -# -# SENAITE.CORE is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright 2018-2020 by it's authors. -# Some rights reserved, see README and LICENSE. - -from bika.lims import bikaMessageFactory as _, t -from Products.CMFCore.utils import getToolByName -from Products.CMFPlone.utils import safe_unicode -from bika.lims.utils import to_utf8, createPdf -from bika.lims.browser import BrowserView -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile -from plone.resource.utils import iterDirectoriesOfType, queryResourceDirectory -import App -import tempfile -import os -import glob -import traceback - - -class PrintForm(BrowserView): - template = ViewPageTemplateFile("templates/print_form.pt") - _DEFAULT_TEMPLATE = 'default_form.pt' - _TEMPLATES_DIR = 'templates/print' - _TEMPLATES_ADDON_DIR = 'samplingrounds' - _current_sr_index = 0 - _samplingrounds = [] - - def __call__(self): - if self.context.portal_type == 'SamplingRound': - self._samplingrounds = [self.context] - - elif self.context.portal_type == 'SamplingRounds' \ - and self.request.get('items', ''): - uids = self.request.get('items').split(',') - uc = getToolByName(self.context, 'uid_catalog') - self._samplingrounds = [obj.getObject() for obj in uc(UID=uids)] - - else: - # Warn and redirect to referer - logger.warning('PrintView: type not allowed: %s' % - self.context.portal_type) - self.destination_url = self.request.get_header("referer", - self.context.absolute_url()) - - # Do print? - if self.request.form.get('pdf', '0') == '1': - response = self.request.response - response.setHeader("Content-type", "application/pdf") - response.setHeader("Content-Disposition", "inline") - response.setHeader("filename", "temp.pdf") - return self.pdfFromPOST() - else: - return self.template() - - def getSamplingRoundObj(self): - """Returns the sampling round object - """ - return self.context - - def getSRTemplates(self): - """ - Returns a DisplayList with the available templates found in - browser/samplinground/templates/ - """ - this_dir = os.path.dirname(os.path.abspath(__file__)) - templates_dir = os.path.join(this_dir, self._TEMPLATES_DIR) - tempath = '%s/%s' % (templates_dir, '*.pt') - templates = [t.split('/')[-1] for t in glob.glob(tempath)] - out = [] - for template in templates: - out.append({'id': template, 'title': template[:-3]}) - for templates_resource in iterDirectoriesOfType(self._TEMPLATES_ADDON_DIR): - prefix = templates_resource.__name__ - templates = [ - tpl for tpl in templates_resource.listDirectory() - if tpl.endswith('.pt') - ] - for template in templates: - out.append({ - 'id': '{0}:{1}'.format(prefix, template), - 'title': '{0} ({1})'.format(template[:-3], prefix), - }) - return out - - def getFormTemplate(self): - """Returns the current samplinground rendered with the template - specified in the request (param 'template'). - Moves the iterator to the next samplinground available. - """ - templates_dir = self._TEMPLATES_DIR - embedt = self.request.get('template', self._DEFAULT_TEMPLATE) - if embedt.find(':') >= 0: - prefix, embedt = embedt.split(':') - templates_dir = queryResourceDirectory(self._TEMPLATES_ADDON_DIR, prefix).directory - embed = ViewPageTemplateFile(os.path.join(templates_dir, embedt)) - reptemplate = "" - try: - reptemplate = embed(self) - except: - tbex = traceback.format_exc() - wsid = self._samplingrounds[self._current_sr_index].id - reptemplate = "
%s - %s '%s':
%s
" % (wsid, _("Unable to load the template"), embedt, tbex) - if self._current_sr_index < len(self._samplingrounds): - self._current_sr_index += 1 - return reptemplate - - def getCSS(self): - """ Returns the css style to be used for the current template. - If the selected template is 'default.pt', this method will - return the content from 'default.css'. If no css file found - for the current template, returns empty string - """ - template = self.request.get('template', self._DEFAULT_TEMPLATE) - content = '' - if template.find(':') >= 0: - prefix, template = template.split(':') - resource = queryResourceDirectory( - self._TEMPLATES_ADDON_DIR, prefix) - css = '{0}.css'.format(template[:-3]) - if css in resource.listDirectory(): - content = resource.readFile(css) - else: - this_dir = os.path.dirname(os.path.abspath(__file__)) - templates_dir = os.path.join(this_dir, self._TEMPLATES_DIR) - path = '%s/%s.css' % (templates_dir, template[:-3]) - with open(path, 'r') as content_file: - content = content_file.read() - return content - - def getAnalysisRequestTemplatesInfo(self): - """ - Returns a lost of dicts with the analysis request templates infomration - [{'uid':'xxxx','id':'xxxx','title':'xxx','url':'xxx'}, ...] - """ - arts_list = [] - for art in self.context.ar_templates: - pc = getToolByName(self.context, 'portal_catalog') - contentFilter = {'portal_type': 'ARTemplate', - 'UID': art} - art_brain = pc(contentFilter) - if len(art_brain) == 1: - art_obj = art_brain[0].getObject() - arts_list.append({ - 'uid': art_obj.UID(), - 'id': art_obj.id, - 'title': art_obj.title, - 'url': art_obj.absolute_url(), - }) - return arts_list - - def getAnalysisRequestBySample(self): - """ - Returns a list of dictionaries sorted by Sample Partition/Container - [{'requests and partition info'}, ...] - """ - # rows will contain the data for each html row - rows = [] - # columns will be used to sort and define the columns - columns = { - 'column_order': [ - 'sample_id', - 'sample_type', - 'sampling_point', - 'sampling_date', - 'analyses', - ], - 'titles': { - 'sample_id': _('Sample ID'), - 'sample_type': _('Sample Type'), - 'sampling_point': _('Sampling Point'), - 'sampling_date': _('Sampling Date'), - 'analyses': _('Analysis'), - } - } - ars = self.context.getAnalysisRequests() - for ar in ars: - ar = ar.getObject() - arcell = False - analyses = ar.getAnalyses() - numans = len(analyses) - for analysis in analyses: - row = { - 'sample_id': { - 'hidden': True if arcell else False, - 'rowspan': numans, - 'value': ar.getId(), - }, - 'sample_type': { - 'hidden': True if arcell else False, - 'rowspan': numans, - 'value': ar.getSampleType().title, - }, - 'sampling_point': { - 'hidden': True if arcell else False, - 'rowspan': numans, - 'value': ar.getSamplePoint().title if ar.getSamplePoint() else '', - }, - 'sampling_date': { - 'hidden': True if arcell else False, - 'rowspan': numans, - 'value': self.context.sampling_date, - }, - 'analyses': { - 'title': analysis.title, - 'units': analysis.getUnit, - }, - } - rows.append(row) - arcell = True - - # table will contain the data that from where the html - # will take the info - table = { - 'columns': columns, - 'rows': rows, - } - return table - - def getLab(self): - return self.context.bika_setup.laboratory.getLabURL() - - def getLogo(self): - portal = self.context.portal_url.getPortalObject() - return "%s/logo_print.png" % portal.absolute_url() - - def pdfFromPOST(self): - """ - It returns the pdf for the sampling rounds printed - """ - html = self.request.form.get('html') - style = self.request.form.get('style') - reporthtml = "%s
%s" % (style, html) - return self.printFromHTML(safe_unicode(reporthtml).encode('utf-8')) - - def printFromHTML(self, sr_html): - """ - Tis function generates a pdf file from the html - :sr_html: the html to use to generate the pdf - """ - # HTML written to debug file - debug_mode = App.config.getConfiguration().debug_mode - if debug_mode: - tmp_fn = tempfile.mktemp(suffix=".html") - open(tmp_fn, "wb").write(sr_html) - - # Creates the pdf - # we must supply the file ourself so that createPdf leaves it alone. - pdf_fn = tempfile.mktemp(suffix=".pdf") - pdf_report = createPdf(htmlreport=sr_html, outfile=pdf_fn) - return pdf_report diff --git a/bika/lims/browser/samplinground/templates/print/default_form.css b/bika/lims/browser/samplinground/templates/print/default_form.css deleted file mode 100644 index 96c36c588c..0000000000 --- a/bika/lims/browser/samplinground/templates/print/default_form.css +++ /dev/null @@ -1,60 +0,0 @@ - -.barcode-container { - width:100%; -} -div.report_body { - font-size:0.8em; -} -div.report_body a { - color:#000; - text-decoration:none; -} -div.report_body h1 { - padding-top:15px; - font-size:1.7em; -} -div#title{ - font-size:1.5em; -} -.label { - font-weight: bold; -} -.table-text { - position: relative; -} -.data-input{ - border: 1px solid #cdcdcd; - height: 20px; -} -table.samples-grid tr td { - vertical-align:top; - border: 1px solid #cdcdcd; - padding: 5px; -} -table thead th{ - border: 1px solid #cdcdcd; - background-color: #808080; -} -#sampling-round-info div { - float: left; - font-size: 0.85em; - position: relative; - width: 150px; -} -span.units { - font-size: 0.7em; -} -div.lab-logo { - float: right; - position: relative; -} -p { - margin:0; - padding:0; -} -.clearfix { - clear:both; -} -#sampling-round-data-entry { - clear: both; -} diff --git a/bika/lims/browser/samplinground/templates/print/default_form.pt b/bika/lims/browser/samplinground/templates/print/default_form.pt deleted file mode 100644 index ba7c04f27d..0000000000 --- a/bika/lims/browser/samplinground/templates/print/default_form.pt +++ /dev/null @@ -1,134 +0,0 @@ - - - - - -
-
-

Description

-

-
-
-

Sampling round template

-

- - - -

-
-

Sampler

-

-
-
-

Department

-

- - - -

-
-
-

Sampling frequency

-

-
-
-

Sampling date

-

-
-
-

Environmental conditions

-

-
-
-

Sampling instructions

-

-
-
-

Samples templates

-

- - -
-
-

-
-
-

Sample points

-

-
-
-

Containers

-

-
-
 
-
- -
- - - - - - - - - - - - - - - - - -
-
-
-
- -
- -
-
-
-
-
-
- -
-
diff --git a/bika/lims/browser/samplinground/templates/print_form.pt b/bika/lims/browser/samplinground/templates/print_form.pt deleted file mode 100644 index 0d9ff019f3..0000000000 --- a/bika/lims/browser/samplinground/templates/print_form.pt +++ /dev/null @@ -1,209 +0,0 @@ - - - - - -
- - -
-
-
-
- - -
-
- - -
-
-
-    - -
-
- - - -
-
-
- - -
- - diff --git a/bika/lims/browser/srtemplate/__init__.py b/bika/lims/browser/srtemplate/__init__.py deleted file mode 100644 index b54d2c0984..0000000000 --- a/bika/lims/browser/srtemplate/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of SENAITE.CORE. -# -# SENAITE.CORE is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright 2018-2020 by it's authors. -# Some rights reserved, see README and LICENSE. diff --git a/bika/lims/browser/srtemplate/artemplates.py b/bika/lims/browser/srtemplate/artemplates.py deleted file mode 100644 index 08267a7a5e..0000000000 --- a/bika/lims/browser/srtemplate/artemplates.py +++ /dev/null @@ -1,211 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of SENAITE.CORE. -# -# SENAITE.CORE is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright 2018-2020 by it's authors. -# Some rights reserved, see README and LICENSE. - -from AccessControl import ClassSecurityInfo -from bika.lims import bikaMessageFactory as _ -from bika.lims.utils import t -from bika.lims.browser.bika_listing import BikaListingView -from Products.Archetypes.Registry import registerWidget -from Products.Archetypes.Widget import TypesWidget -from Products.CMFCore.utils import getToolByName - - -class AnalysisRequestTemplatesView(BikaListingView): - """ BIKA listing to display ARTemplates for an SRTemplate. - """ - - def __init__(self, context, request): - super(AnalysisRequestTemplatesView, self).__init__(context, request) - self.catalog = "bika_setup_catalog" - self.context_actions = {} - self.base_url = self.context.absolute_url() - self.view_url = self.base_url - - self.show_select_row = False - self.show_select_all_checkbox = False - self.show_column_toggles = False - self.show_select_column = True - self.show_categories = True - self.expand_all_categories = True - self.pagesize = 50 - self.title = self.context.translate(_("Sample Templates")) - self.icon = self.portal_url + "/++resource++bika.lims.images/artemplate_big.png" - self.form_id = "artemplates" - self.columns = { - 'title': { - 'title': _('Template Title'), - 'index': 'sortable_title', - 'sortable': True, - }, - 'SamplePoint': { - 'title': _('Sample Point'), - 'index': 'sortable_title', - 'sortable': True, - }, - 'SampleType': { - 'title': _('Sample Type'), - 'index': 'sortable_title', - 'sortable': True, - }, - 'Composite': { - 'title': _('Composite Y/N'), - 'index': 'sortable_title', - 'sortable': True, - }, - 'ContainerTitle': { - 'title': _('Container Title'), - 'index': 'sortable_title', - 'sortable': True, - }, - 'ContainerVolume': { - 'title': _('Container Volume'), - 'index': 'sortable_title', - 'sortable': True, - }, - 'Preservation': { - 'title': _('Preservation'), - 'index': 'sortable_title', - 'sortable': True, - }, - 'Sampler': { - 'title': _('Sampler'), - 'sortable': True, - }, - 'PreparationMethod': { - 'title': _('Preservation Method'), - 'index': 'sortable_title', - 'sortable': True, - }, - } - self.review_states = [ - {'id': 'default', - 'title': _('Active'), - 'contentFilter': {'is_active': True}, - 'transitions': [{'id': 'deactivate'}, ], - 'columns': ['title', - 'SamplePoint', - 'SampleType', - 'Composite', - 'ContainerTitle', - 'ContainerVolume', - 'Preservation', - #'Sampler', - 'PreparationMethod']}, - {'id': 'inactive', - 'title': _('Inactive'), - 'contentFilter': {'is_active': False}, - 'transitions': [{'id': 'activate'}, ], - 'columns': ['title', - 'SamplePoint', - 'SampleType', - 'Composite', - 'ContainerTitle', - 'ContainerVolume', - 'Preservation', - #'Sampler', - 'PreparationMethod']}, - {'id': 'all', - 'title': _('All'), - 'contentFilter': {}, - 'columns': ['title', - 'SamplePoint', - 'SampleType', - 'Composite', - 'ContainerTitle', - 'ContainerVolume', - 'Preservation', - #'Sampler', - 'PreparationMethod']}, - ] - - def contentsMethod(self, contentFilter): - return self.context.getARTemplates() - - def _buildFromPerPartition(self, item, partition): - """ - This function will get the partition info and then it'll write the container and preservation data - to the dictionary 'item' - :param item: a dict which contains the ARTeplate data columns - :param partition: a dict with some partition info - :returns: the item dict with the partition's data - """ - uc = getToolByName(self, 'uid_catalog') - container = uc(UID=partition.get('container_uid', '')) - preservation = uc(UID=partition.get('preservation_uid', '')) - if container: - container = container[0].getObject() - item['ContainerTitle'] = container.title - item['replace']['ContainerTitle'] = "%s" % \ - (container.absolute_url(), item['ContainerTitle']) - item['ContainerVolume'] = container.getCapacity() - else: - item['ContainerTitle'] = '' - item['ContainerVolume'] = '' - if preservation: - preservation = preservation[0].getObject() - item['Preservation'] = preservation.title - item['replace']['Preservation'] = "%s" % \ - (preservation.absolute_url(), item['Preservation']) - else: - item['Preservation'] = '' - item['PreparationMethod'] = '' - return item - - def folderitems(self): - items = BikaListingView.folderitems(self) - new_items = [] - for item in items: - if not item.has_key('obj'): continue - obj = item['obj'] - # Updating some ARTemplate columns - title_link = "%s" % (item['url'], item['title']) - item['replace']['title'] = title_link - if obj.getSamplePoint(): - item['SamplePoint'] = obj.getSamplePoint().title - item['replace']['SamplePoint'] = "%s" % \ - (obj.getSamplePoint().absolute_url(), item['SamplePoint']) - else: - item['SamplePoint'] = '' - if obj.getSamplePoint(): - item['SamplePoint'] = obj.getSamplePoint().title - item['replace']['SamplePoint'] = "%s" % \ - (obj.getSamplePoint().absolute_url(), item['SamplePoint']) - else: - item['SamplePoint'] = '' - if obj.getSampleType(): - item['SampleType'] = obj.getSampleType().title - item['replace']['SampleType'] = "%s" % \ - (obj.getSampleType().absolute_url(), item['SampleType']) - else: - item['SampleType'] = '' - item['Composite'] = obj.getComposite() - img_url = '' - item['replace']['Composite'] = img_url if obj.getComposite() else ' ' - - partitions = obj.getPartitions() - for partition in partitions: - c_item = item.copy() - # We ave to make a copy of 'replace' because it's a reference to a dict object - c_item['replace'] = item['replace'].copy() - # Adding the partition info - c_item = self._buildFromPerPartition(c_item, partition) - # Adding the ARTemplate item to the future list to display - new_items.append(c_item) - return new_items diff --git a/bika/lims/browser/srtemplate/configure.zcml b/bika/lims/browser/srtemplate/configure.zcml deleted file mode 100644 index 77e32d9cef..0000000000 --- a/bika/lims/browser/srtemplate/configure.zcml +++ /dev/null @@ -1,14 +0,0 @@ - - - - diff --git a/bika/lims/browser/widgets/__init__.py b/bika/lims/browser/widgets/__init__.py index bb1b901bce..af0f50bc99 100644 --- a/bika/lims/browser/widgets/__init__.py +++ b/bika/lims/browser/widgets/__init__.py @@ -33,7 +33,6 @@ from .analysisprofileanalyseswidget import AnalysisProfileAnalysesWidget from .artemplateanalyseswidget import ARTemplateAnalysesWidget from .artemplatepartitionswidget import ARTemplatePartitionsWidget -from .srtemplateartemplateswidget import SRTemplateARTemplatesWidget from .addresswidget import AddressWidget from .scheduleinputwidget import ScheduleInputWidget from .integer import IntegerWidget diff --git a/bika/lims/browser/widgets/srtemplateartemplateswidget.py b/bika/lims/browser/widgets/srtemplateartemplateswidget.py deleted file mode 100644 index ad8ae4ef8a..0000000000 --- a/bika/lims/browser/widgets/srtemplateartemplateswidget.py +++ /dev/null @@ -1,121 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of SENAITE.CORE. -# -# SENAITE.CORE is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright 2018-2020 by it's authors. -# Some rights reserved, see README and LICENSE. - -from AccessControl import ClassSecurityInfo -from bika.lims import bikaMessageFactory as _ -from bika.lims.utils import t -from bika.lims.browser.bika_listing import BikaListingView -from Products.Archetypes.Registry import registerWidget -from Products.Archetypes.Widget import TypesWidget -from Products.CMFCore.utils import getToolByName - - -class SRTemplateARTemplatesView(BikaListingView): - """ BIKA listing to display ARTemplates for an SRTemplate. - """ - - def __init__(self, context, request, fieldvalue, allow_edit): - super(SRTemplateARTemplatesView, self).__init__(context, request) - self.catalog = "bika_setup_catalog" - self.contentFilter = { - 'portal_type': 'ARTemplate', - 'sort_on': 'title', - 'is_active': True, - } - self.context_actions = {} - self.base_url = self.context.absolute_url() - self.view_url = self.base_url - - self.show_select_row = False - self.show_select_all_checkbox = False - self.show_column_toggles = False - self.show_select_column = True - self.show_categories = True - self.expand_all_categories = True - self.pagesize = 999999 - self.allow_edit = allow_edit - self.clientUID = None - self.form_id = "artemplates" - self.columns = { - 'Title': { - 'title': _('Service'), - 'index': 'title', - 'replace_url': 'absolute_url', - 'sortable': False, - }, - } - self.review_states = [{ - 'id':'default', - 'title': _('All'), - 'contentFilter':{}, - 'columns': ['Title'], - 'transitions': [{'id':'empty'}], - }] - self.fieldvalue = fieldvalue - self.selected = [o.UID() for o in fieldvalue] - - def isItemAllowed(self, obj): - if self.clientUID is None: - self.clientUID = self.context.aq_parent.aq_parent.UID() - # Only display client's and lab's arts - if obj.aq_parent.aq_inner.meta_type == 'Client': - obj_client = obj.getClientUID() - if obj_client != self.clientUID: - return False - return True - - def folderitem(self, obj, item, index): - item['selected'] = item['uid'] in self.selected - return item - - -class SRTemplateARTemplatesWidget(TypesWidget): - _properties = TypesWidget._properties.copy() - _properties.update({ - 'macro': "bika_widgets/srtemplateartemplateswidget", - }) - - security = ClassSecurityInfo() - - security.declarePublic('process_form') - def process_form(self, instance, field, form, empty_marker = None, - emptyReturnsMarker = False): - bsc = getToolByName(instance, 'bika_setup_catalog') - value = [] - service_uids = form.get('uids', None) - return service_uids, {} - - security.declarePublic('ARTemplates') - def ARTemplates(self, field, allow_edit = False): - fieldvalue = getattr(field, field.accessor)() - view = SRTemplateARTemplatesView( - self, - self.REQUEST, - fieldvalue = fieldvalue, - allow_edit = allow_edit - ) - return view.contents_table(table_only = True) - - -registerWidget( - SRTemplateARTemplatesWidget, - title = 'SR Template Sample Templates Selector', - description = ('SR Template Sample Templates Selector'), -) diff --git a/bika/lims/content/analysisrequest.py b/bika/lims/content/analysisrequest.py index 123118f3c4..376e14a123 100644 --- a/bika/lims/content/analysisrequest.py +++ b/bika/lims/content/analysisrequest.py @@ -116,7 +116,6 @@ from bika.lims.permissions import FieldEditSampler from bika.lims.permissions import FieldEditSamplingDate from bika.lims.permissions import FieldEditSamplingDeviation -from bika.lims.permissions import FieldEditSamplingRound from bika.lims.permissions import FieldEditScheduledSampler from bika.lims.permissions import FieldEditSpecification from bika.lims.permissions import FieldEditStorageLocation @@ -333,27 +332,6 @@ ), ), - ReferenceField( - 'SamplingRound', - allowed_types=('SamplingRound',), - relationship='AnalysisRequestSamplingRound', - mode="rw", - read_permission=View, - write_permission=FieldEditSamplingRound, - widget=ReferenceWidget( - label=_("Sampling Round"), - description=_("The assigned sampling round of this request"), - size=20, - render_own_label=True, - visible={ - 'add': 'invisible', - }, - catalog_name='portal_catalog', - base_query={}, - showOn=True, - ), - ), - ReferenceField( 'SubGroup', required=False, @@ -1161,12 +1139,6 @@ expression="here._getCreatorEmail()", widget=ComputedWidget(visible=False), ), - ComputedField( - 'SamplingRoundUID', - expression="here.getSamplingRound().UID() " \ - "if here.getSamplingRound() else ''", - widget=ComputedWidget(visible=False), - ), ComputedField( 'SamplerFullName', expression="here._getSamplerFullName()", @@ -1913,16 +1885,6 @@ def isInvalid(self): workflow = getToolByName(self, 'portal_workflow') return workflow.getInfoFor(self, 'review_state') == 'invalid' - def getSamplingRoundUID(self): - """Obtains the sampling round UID - :returns: UID - """ - sr = self.getSamplingRound() - if sr: - return sr.UID() - else: - return '' - def getStorageLocationTitle(self): """ A method for AR listing catalog metadata :return: Title of Storage Location diff --git a/bika/lims/content/configure.zcml b/bika/lims/content/configure.zcml index 3df4d05458..de43135625 100644 --- a/bika/lims/content/configure.zcml +++ b/bika/lims/content/configure.zcml @@ -7,8 +7,6 @@ i18n_domain="senaite.core"> - - [(ART.title),(ART.UID),...] - """ - l = [] - art_uids = self.ar_templates - # I have to get the catalog in this way because I can't do it with 'self'... - pc = getToolByName(api.portal.get(), 'uid_catalog') - for art_uid in art_uids: - art_obj = pc(UID=art_uid) - if len(art_obj) != 0: - l.append((art_obj[0].Title, art_uid)) - return l - - def getDepartmentInfo(self): - """ - Returns a dict with the department infomration - {'uid':'xxxx','id':'xxxx','title':'xxx','url':'xxx'} - """ - pc = getToolByName(api.portal.get(), 'portal_catalog') - contentFilter = {'portal_type': 'Department', - 'UID': self.department} - departmentlist = pc(contentFilter) - departmentdict = {'uid': '', 'id': '', 'title': '', 'url': ''} - if len(departmentlist) == 1: - department = departmentlist[0].getObject() - departmentdict = { - 'uid': department.id, - 'id': department.UID(), - 'title': department.title, - 'url': department.absolute_url(), - } - else: - from bika.lims import logger - error = "Error when looking for department with uid '%s'. " - logger.exception(error, self.department) - return departmentdict - - def getSRTemplateInfo(self): - """ - Returns a dict with the SRTemplate infomration - {'uid':'xxxx','id':'xxxx','title':'xxx','url':'xxx'} - """ - pc = getToolByName(api.portal.get(), 'portal_catalog') - contentFilter = {'portal_type': 'SRTemplate', - 'UID': self.sr_template} - srt = pc(contentFilter) - srtdict = {'uid': '', 'id': '', 'title': '', 'url': ''} - if len(srt) == 1: - template = srt[0].getObject() - srtdict = { - 'uid': template.id, - 'id': template.UID(), - 'title': template.title, - 'url': template.absolute_url(), - } - else: - from bika.lims import logger - error = "Error when looking for sr template with uid '%s'. " - logger.exception(error, self.sr_template) - return srtdict - - def getClientContact(self): - """ - Returns info from the Client contact who coordinates with the lab - """ - pc = getToolByName(api.portal.get(), 'portal_catalog') - contentFilter = {'portal_type': 'Contact', - 'id': self.client_contact} - cnt = pc(contentFilter) - cntdict = {'uid': '', 'id': '', 'fullname': '', 'url': ''} - if len(cnt) == 1: - cnt = cnt[0].getObject() - cntdict = { - 'uid': cnt.id, - 'id': cnt.UID(), - 'fullname': cnt.getFullname(), - 'url': cnt.absolute_url(), - } - else: - from bika.lims import logger - error = "Error when looking for contact with id '%s'. " - logger.exception(error, self.client_contact) - return cntdict - - def getClientInChargeAtSamplingTime(self): - """ - Returns info from the Client contact who is in charge at sampling time - """ - pc = getToolByName(api.portal.get(), 'portal_catalog') - contentFilter = {'portal_type': 'Contact', - 'id': self.client_contact_in_charge_at_sampling_time} - cnt = pc(contentFilter) - cntdict = {'uid': '', 'id': '', 'fullname': '', 'url': ''} - if len(cnt) == 1: - cnt = cnt[0].getObject() - cntdict = { - 'uid': cnt.id, - 'id': cnt.UID(), - 'fullname': cnt.getFullname(), - 'url': cnt.absolute_url(), - } - else: - from bika.lims import logger - error = "Error when looking for contact with id '%s'. " - logger.exception( - error, self.client_contact_in_charge_at_sampling_time) - return cntdict - - def hasUserAddEditPermission(self): - """ - Checks if the current user has privileges to access to the editing view. - From Jira LIMS-1549: - - Creation/Edit: Lab manager, Client Contact, Lab Clerk, Client Contact (for Client-specific SRTs) - :returns: True/False - """ - mtool = getToolByName(self, 'portal_membership') - checkPermission = mtool.checkPermission - # In bika_samplinground_workflow.csv there are defined the ModifyPortalContent statements. There is said that - # client has ModifyPortalContent permission enabled, so here we have to check if the client satisfy the - # condition wrote in the function's description - if (checkPermission(ModifyPortalContent, self) or checkPermission(AddPortalContent, self)) \ - and 'Client' in api.user.get_current().getRoles(): - # Checking if the current user is a current client's contact - userID = api.user.get_current().id - contact_objs = self.getContacts() - contact_ids = [obj.getUsername() for obj in contact_objs] - if userID in contact_ids: - return True - else: - return False - return checkPermission(ModifyPortalContent, self) or checkPermission(AddPortalContent, self) - - def workflow_script_cancel(self): - """ - When the round is cancelled, all its associated Samples and ARs are cancelled by the system. - """ - if skip(self, "cancel"): - return - self.reindexObject(idxs=["is_active", ]) - # deactivate all analysis requests in this sampling round. - analysis_requests = self.getAnalysisRequests() - for ar in analysis_requests: - ar_obj = ar.getObject() - workflow = getToolByName(self, 'portal_workflow') - if workflow.getInfoFor(ar_obj, 'review_state') != 'cancelled': - doActionFor(ar.getObject(), 'cancel') diff --git a/bika/lims/content/srtemplate.py b/bika/lims/content/srtemplate.py deleted file mode 100644 index af2a8dc6f3..0000000000 --- a/bika/lims/content/srtemplate.py +++ /dev/null @@ -1,140 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of SENAITE.CORE. -# -# SENAITE.CORE is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright 2018-2020 by it's authors. -# Some rights reserved, see README and LICENSE. - -import sys - -from AccessControl import ClassSecurityInfo -from Products.Archetypes.public import * -from Products.Archetypes.references import HoldingReference -from Products.CMFCore.utils import getToolByName -from bika.lims import bikaMessageFactory as _ -from bika.lims.browser.widgets import SRTemplateARTemplatesWidget -from bika.lims.config import PROJECTNAME -from bika.lims.content.bikaschema import BikaSchema -from bika.lims.idserver import renameAfterCreation -from bika.lims.interfaces import ISamplingRoundTemplate, IDeactivable -from bika.lims.utils import getUsers -from zope.interface import implements - -schema = BikaSchema.copy() + Schema(( - - # The default sampler for the rounds - StringField('Sampler', - required=1, - searchable=True, - vocabulary='_getSamplersDisplayList', - widget=SelectionWidget( - format='select', - label = _("Sampler"), - ), - ), - - # The department responsible for the sampling round - ReferenceField('Department', - required=1, - vocabulary_display_path_bound=sys.maxint, - allowed_types=('Department',), - vocabulary='_getDepartmentsDisplayList', - relationship='SRTemplateDepartment', - referenceClass=HoldingReference, - widget=ReferenceWidget( - checkbox_bound=0, - label = _("Department"), - description = _("The laboratory department"), - catalog_name='bika_setup_catalog', - base_query={'is_active': True}, - ), - ), - - # The number of days between recurring field trips - IntegerField('SamplingDaysFrequency', - required=1, - default=7, - widget=IntegerWidget( - label = _("Sampling Frequency"), - description=_( - "The number of days between recurring field trips"), - ), - ), - - TextField('Instructions', - searchable = True, - default_content_type = 'text/plain', - allowed_content_types= ('text/plain'), - default_output_type="text/plain", - widget = TextAreaWidget( - label=_("Instructions"), - append_only = False, - ), - ), - - ReferenceField('ARTemplates', - schemata = 'AR Templates', - required = 1, - multiValued = 1, - allowed_types = ('ARTemplate',), - relationship = 'SRTemplateARTemplate', - widget = SRTemplateARTemplatesWidget( - label=_("Sample Templates"), - description=_("Select Sample Templates to include"), - ) - ), -)) - -schema['description'].widget.visible = True -schema['title'].widget.visible = True -schema['title'].validators = ('uniquefieldvalidator',) -# Update the validation layer after change the validator in runtime -schema['title']._validationLayer() - - -class SRTemplate(BaseContent): - implements(ISamplingRoundTemplate, IDeactivable) - security = ClassSecurityInfo() - schema = schema - displayContentsTab = False - - _at_rename_after_creation = True - def _renameAfterCreation(self, check_auto_id=False): - renameAfterCreation(self) - - def _getSamplersDisplayList(self): - """ Returns the available users in the system with the roles - 'LabManager' and/or 'Sampler' - """ - return getUsers(self, ['LabManager', 'Sampler']) - - def _getDepartmentsDisplayList(self): - """ Returns the available departments in the system. Only the - active departments are shown, unless the object has an - inactive department already assigned. - """ - bsc = getToolByName(self, 'bika_setup_catalog') - items = [('', '')] + [(o.UID, o.Title) for o in - bsc(portal_type='Department', - is_active=True)] - o = self.getDepartment() - if o and o.UID() not in [i[0] for i in items]: - items.append((o.UID(), o.Title())) - items.sort(lambda x, y: cmp(x[1], y[1])) - return DisplayList(list(items)) - - -registerType(SRTemplate, PROJECTNAME) diff --git a/bika/lims/controlpanel/bika_samplingrounds.py b/bika/lims/controlpanel/bika_samplingrounds.py index 3a31ad3856..da97ad498b 100644 --- a/bika/lims/controlpanel/bika_samplingrounds.py +++ b/bika/lims/controlpanel/bika_samplingrounds.py @@ -18,99 +18,18 @@ # Copyright 2018-2020 by it's authors. # Some rights reserved, see README and LICENSE. -from bika.lims import bikaMessageFactory as _ -from bika.lims.browser.bika_listing import BikaListingView from plone.dexterity.content import Container from plone.supermodel import model from zope.interface import implements -class SamplingRoundsView(BikaListingView): - """Displays all system's sampling rounds - """ - - def __init__(self, context, request): - super(SamplingRoundsView, self).__init__(context, request) - self.catalog = "portal_catalog" - self.contentFilter = { - 'portal_type': 'SamplingRound', - 'sort_on': 'sortable_title' - } - - self.show_select_row = False - self.show_select_column = True - self.pagesize = 25 - self.form_id = "samplinground" - self.icon = self.portal_url + "/++resource++bika.lims.images/instrumentcertification_big.png" - self.title = self.context.translate(_("Sampling Rounds")) - self.description = "" - # Hide the ugly edit-bar with 'new', 'draft', etc - # self.request.set('disable_border', 1) - self.columns = { - 'title': {'title': _('Title'), - 'sortable': True, - 'toggle': True, - 'replace_url': 'absolute_url'}, - 'Description': {'title': _('Description')}, - 'num_sample_points': {'title': _('Number of sampling points'), - 'index': 'sortable_title'}, - 'num_containers': {'title': _('Number of containers'), - 'index': 'sortable_title'}, - } - self.review_states = [ - {'id': 'default', - 'title': _('Open'), - 'contentFilter': {'review_state': 'open'}, - 'columns': ['title', - 'Description', - 'num_sample_points', - 'num_containers', - ] - }, - {'id': 'closed', - 'contentFilter': {'review_state': 'closed'}, - 'title': _('Closed'), - 'transitions': [{'id': 'open'}], - 'columns': ['title', - 'Description', - 'num_sample_points', - 'num_containers', - ] - }, - {'id': 'cancelled', - 'title': _('Cancelled'), - 'transitions': [{'id': 'reinstate'}], - 'contentFilter': {'review_state': 'cancelled'}, - 'columns': ['title', - 'Description', - 'num_sample_points', - 'num_containers', - ] - }, - {'id': 'all', - 'title': _('All'), - 'transitions': [], - 'contentFilter':{}, - 'columns': ['title', - 'Description', - 'num_sample_points', - 'num_containers', - ] - }, - ] - - def before_render(self): - """Before template render hook - """ - # Don't allow any context actions - self.request.set("disable_border", 1) - - +# TODO: Legacy type. Remove after 1.3.3 class ISamplingRounds(model.Schema): """ A Sampling Rounds container. """ +# TODO: Legacy type. Remove after 1.3.3 class SamplingRounds(Container): implements(ISamplingRounds) displayContentsTab = False diff --git a/bika/lims/controlpanel/bika_srtemplates.py b/bika/lims/controlpanel/bika_srtemplates.py index c99bbdaffa..948d10a4ff 100644 --- a/bika/lims/controlpanel/bika_srtemplates.py +++ b/bika/lims/controlpanel/bika_srtemplates.py @@ -18,99 +18,19 @@ # Copyright 2018-2020 by it's authors. # Some rights reserved, see README and LICENSE. -from bika.lims import bikaMessageFactory as _ -from bika.lims.browser.bika_listing import BikaListingView -from bika.lims.config import PROJECTNAME -from bika.lims.interfaces import ISamplingRoundTemplates -from bika.lims.permissions import AddSRTemplate -from bika.lims.utils import checkPermissions +from Products.ATContentTypes.content import schemata +from Products.Archetypes import atapi from plone.app.folder.folder import ATFolder from plone.app.folder.folder import ATFolderSchema -from Products.Archetypes import atapi -from Products.ATContentTypes.content import schemata -from Products.CMFCore.permissions import AddPortalContent -from Products.CMFCore.permissions import ModifyPortalContent from zope.interface.declarations import implements - -class SamplingRoundTemplatesView(BikaListingView): - """ - Displays the list of Sampling Round Templates registered in the system. - For users with 'Bika: Add SRTemplate' permission granted (along with - ModifyPortalContent and AddPortalContent), an "Add" button will be - displayed at the top of the list. - """ - - def __init__(self, context, request): - super(SamplingRoundTemplatesView, self).__init__(context, request) - self.form_id = "srtemplates" - self.show_select_column = True - self.icon = self.portal_url + "/++resource++bika.lims.images/srtemplate_big.png" - self.title = self.context.translate(_("Sampling Round Templates")) - self.catalog = "bika_setup_catalog" - self.contentFilter = { - 'portal_type': 'SRTemplate', - 'sort_order': 'sortable_title', - 'path': { - "query": "/".join(self.context.getPhysicalPath()), - "level": 0 - }, - } - self.columns = { - 'Title': { - 'title': _('Template'), - 'index': 'sortable_title', - 'replace_url': 'absolute_url' - }, - 'Description': { - 'title': _('Description'), - 'index': 'description' - }, - } - self.review_states = [ - {'id':'default', - 'title': _('Active'), - 'contentFilter': {'is_active': True}, - 'columns': ['Title', - 'Description']}, - {'id':'inactive', - 'title': _('Inactive'), - 'contentFilter': {'is_active': False}, - 'columns': ['Title', - 'Description']}, - {'id':'all', - 'title': _('All'), - 'contentFilter':{}, - 'columns': ['Title', - 'Description']}, - ] - - def __call__(self): - # Has the current user (might be a Client's contact) enough - # privileges to add a Sampling Round Template?. This check must be done - # here in the __call__ function because the user (and checkpermission) - # is only accessible once the object has already been instantiated. - reqperms = [ModifyPortalContent, AddPortalContent, AddSRTemplate] - if checkPermissions(reqperms, self.context): - self.context_actions = { - _('Add'): { - 'url': 'createObject?type_name=SRTemplate', - 'permission': AddSRTemplate, - 'icon': '++resource++bika.lims.images/add.png' - } - } - return super(SamplingRoundTemplatesView, self).__call__() - - def before_render(self): - """Before template render hook - """ - # Don't allow any context actions - self.request.set("disable_border", 1) - +from bika.lims.config import PROJECTNAME +from bika.lims.interfaces import ISamplingRoundTemplates schema = ATFolderSchema.copy() +# TODO: Legacy type. Remove after 1.3.3 class SRTemplates(ATFolder): implements(ISamplingRoundTemplates) displayContentsTab = False diff --git a/bika/lims/controlpanel/configure.zcml b/bika/lims/controlpanel/configure.zcml index 3bdb4ef6e1..817fec7378 100644 --- a/bika/lims/controlpanel/configure.zcml +++ b/bika/lims/controlpanel/configure.zcml @@ -212,14 +212,6 @@ layer="bika.lims.interfaces.IBikaLIMS" /> - - - - - - @@ -91,10 +89,6 @@ # Transition Permissions (Supply Order) - # Transition Permissions (Sampling Round) - - - # Transition Permissions (Worksheet) @@ -132,7 +126,6 @@ - diff --git a/bika/lims/profiles/default/catalog.xml b/bika/lims/profiles/default/catalog.xml index 68dd0bfe5d..2b6cd252c0 100644 --- a/bika/lims/profiles/default/catalog.xml +++ b/bika/lims/profiles/default/catalog.xml @@ -9,10 +9,6 @@ - - - - diff --git a/bika/lims/profiles/default/controlpanel.xml b/bika/lims/profiles/default/controlpanel.xml index ce29a60a5d..dbdc1f9c41 100644 --- a/bika/lims/profiles/default/controlpanel.xml +++ b/bika/lims/profiles/default/controlpanel.xml @@ -275,15 +275,6 @@ senaite.core: Manage Bika - - senaite.core: Manage Bika - - senaite.core: Manage Bika - - senaite.core: Manage Bika - - - diff --git a/bika/lims/profiles/default/jsregistry.xml b/bika/lims/profiles/default/jsregistry.xml index 4e836a8665..e939294025 100644 --- a/bika/lims/profiles/default/jsregistry.xml +++ b/bika/lims/profiles/default/jsregistry.xml @@ -373,28 +373,6 @@ inline="False" insert-after="*"/> - - - - - @@ -98,7 +97,6 @@ - diff --git a/bika/lims/profiles/default/rolemap.xml b/bika/lims/profiles/default/rolemap.xml index 76c86aa8e9..751db2fcfb 100644 --- a/bika/lims/profiles/default/rolemap.xml +++ b/bika/lims/profiles/default/rolemap.xml @@ -330,20 +330,6 @@ - - - - - - - - - - - - - - @@ -507,22 +493,6 @@ - - - - - - - - - - - - - - - - @@ -706,11 +676,6 @@ - - - - - diff --git a/bika/lims/profiles/default/structure/.preserve b/bika/lims/profiles/default/structure/.preserve index cf8da73b00..0ffc0f78c9 100644 --- a/bika/lims/profiles/default/structure/.preserve +++ b/bika/lims/profiles/default/structure/.preserve @@ -8,4 +8,3 @@ methods pricelists bika_setup reports -samplingrounds diff --git a/bika/lims/profiles/default/structure/bika_setup/.objects b/bika/lims/profiles/default/structure/bika_setup/.objects index 06bc8e3f7a..cf076fb8b3 100644 --- a/bika/lims/profiles/default/structure/bika_setup/.objects +++ b/bika/lims/profiles/default/structure/bika_setup/.objects @@ -26,8 +26,6 @@ bika_samplepoints,SamplePoints bika_sampletypes,SampleTypes bika_storagelocations,StorageLocations bika_samplingdeviations,SamplingDeviations -bika_samplingrounds,SamplingRounds -bika_srtemplates,SRTemplates bika_subgroups,SubGroups bika_suppliers,Suppliers bika_worksheettemplates,WorksheetTemplates diff --git a/bika/lims/profiles/default/structure/bika_setup/.preserve b/bika/lims/profiles/default/structure/bika_setup/.preserve index e2ec2f2431..42475a2739 100644 --- a/bika/lims/profiles/default/structure/bika_setup/.preserve +++ b/bika/lims/profiles/default/structure/bika_setup/.preserve @@ -25,8 +25,6 @@ bika_samplematrices bika_samplepoints bika_sampletypes bika_samplingdeviations -bika_samplingrounds -bika_srtemplates bika_storagelocations bika_suppliers bika_subgroups diff --git a/bika/lims/profiles/default/structure/bika_setup/bika_samplingrounds/.object b/bika/lims/profiles/default/structure/bika_setup/bika_samplingrounds/.object deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/bika/lims/profiles/default/structure/bika_setup/bika_samplingrounds/.properties b/bika/lims/profiles/default/structure/bika_setup/bika_samplingrounds/.properties deleted file mode 100644 index e43db52bbe..0000000000 --- a/bika/lims/profiles/default/structure/bika_setup/bika_samplingrounds/.properties +++ /dev/null @@ -1,4 +0,0 @@ -[DEFAULT] -description = -title = Sampling Rounds - diff --git a/bika/lims/profiles/default/structure/bika_setup/bika_srtemplates/.objects b/bika/lims/profiles/default/structure/bika_setup/bika_srtemplates/.objects deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/bika/lims/profiles/default/structure/bika_setup/bika_srtemplates/.properties b/bika/lims/profiles/default/structure/bika_setup/bika_srtemplates/.properties deleted file mode 100644 index 1bf63f9739..0000000000 --- a/bika/lims/profiles/default/structure/bika_setup/bika_srtemplates/.properties +++ /dev/null @@ -1,3 +0,0 @@ -[DEFAULT] -description = -title = Sampling Round Templates diff --git a/bika/lims/profiles/default/types.xml b/bika/lims/profiles/default/types.xml index bb8b017c30..c1dd28fde8 100644 --- a/bika/lims/profiles/default/types.xml +++ b/bika/lims/profiles/default/types.xml @@ -84,10 +84,6 @@ - - - - diff --git a/bika/lims/profiles/default/types/Client.xml b/bika/lims/profiles/default/types/Client.xml index 4507ff3640..89a7623555 100644 --- a/bika/lims/profiles/default/types/Client.xml +++ b/bika/lims/profiles/default/types/Client.xml @@ -25,10 +25,8 @@ - - False @@ -132,30 +130,6 @@ - - - - - - - - - - Sampling Round Template - - ++resource++bika.lims.images/srtemplate.png - SRTemplate - bika.lims - addSRTemplate - - - False - True - - False - False - artemplates - - - - - - - - - - - - - - - - - - diff --git a/bika/lims/profiles/default/types/SRTemplates.xml b/bika/lims/profiles/default/types/SRTemplates.xml deleted file mode 100644 index 9e0492df17..0000000000 --- a/bika/lims/profiles/default/types/SRTemplates.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - Sampling Round Templates - - ++resource++bika.lims.images/srtemplate.png - SRTemplates - bika.lims - addSRTemplates - - - False - True - - - - False - False - - - - - - - diff --git a/bika/lims/profiles/default/types/SamplingRound.xml b/bika/lims/profiles/default/types/SamplingRound.xml deleted file mode 100644 index 7961863c67..0000000000 --- a/bika/lims/profiles/default/types/SamplingRound.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - Sampling Round - A sampling round object - string:${portal_url}/document_icon.png - bika.lims.content.samplingsround - False - True - - - - - False - - - bika.lims.content.samplinground.ISamplingRound - bika.lims.content.samplinground.SamplingRound - - - - - - - - analysisrequests - view - - - - False - cmf.AddPortalContent - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bika/lims/profiles/default/types/SamplingRounds.xml b/bika/lims/profiles/default/types/SamplingRounds.xml deleted file mode 100644 index dd50f89232..0000000000 --- a/bika/lims/profiles/default/types/SamplingRounds.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - Sampling Rounds - Show all the sampling rounds registered in the system - string:${portal_url}/folder_icon.png - bika.lims.controlpanel.bika_samplingrounds - True - True - - - - False - - - bika.lims.controlpanel.bika_samplingrounds.ISamplingRounds - bika.lims.controlpanel.bika_samplingrounds.SamplingRounds - - - - - - - - view - view - - - - False - cmf.AddPortalContent - - - - - - - - - - - - - - - - diff --git a/bika/lims/profiles/default/workflows.xml b/bika/lims/profiles/default/workflows.xml index 7555060146..031ce9c5ea 100644 --- a/bika/lims/profiles/default/workflows.xml +++ b/bika/lims/profiles/default/workflows.xml @@ -9,7 +9,6 @@ - @@ -251,12 +250,6 @@ - - - - - - @@ -381,12 +374,6 @@ - - - - - - diff --git a/bika/lims/profiles/default/workflows/bika_ar_workflow/definition.xml b/bika/lims/profiles/default/workflows/bika_ar_workflow/definition.xml index 6920fcfd02..637a56bfb2 100644 --- a/bika/lims/profiles/default/workflows/bika_ar_workflow/definition.xml +++ b/bika/lims/profiles/default/workflows/bika_ar_workflow/definition.xml @@ -74,7 +74,6 @@ senaite.core: Field: Edit Sampler senaite.core: Field: Edit Sampling Date senaite.core: Field: Edit Sampling Deviation - senaite.core: Field: Edit Sampling Round senaite.core: Field: Edit Scheduled Sampler senaite.core: Field: Edit Specification senaite.core: Field: Edit Storage Location @@ -162,7 +161,6 @@ - @@ -255,7 +253,6 @@ - @@ -354,7 +351,6 @@ - @@ -443,7 +439,6 @@ - @@ -530,7 +525,6 @@ - @@ -613,7 +607,6 @@ - @@ -703,7 +696,6 @@ - @@ -789,7 +781,6 @@ - @@ -876,7 +867,6 @@ - @@ -953,7 +943,6 @@ - @@ -1028,7 +1017,6 @@ - @@ -1103,7 +1091,6 @@ - @@ -1183,7 +1170,6 @@ - diff --git a/bika/lims/profiles/default/workflows/bika_samplinground_workflow/definition.xml b/bika/lims/profiles/default/workflows/bika_samplinground_workflow/definition.xml deleted file mode 100644 index 3a4df5349e..0000000000 --- a/bika/lims/profiles/default/workflows/bika_samplinground_workflow/definition.xml +++ /dev/null @@ -1,140 +0,0 @@ - - - - Add portal content - senaite.core: Add AnalysisRequest - senaite.core: Transition: Close Sampling Round - senaite.core: Transition: Reopen Sampling Round - Modify portal content - View - - - The SamplingRound can't be edited and Samples cannot be attached - - - - - - - - - - - Analyst - Client - LabClerk - LabManager - Manager - Owner - RegulatoryInspector - Verifier - - - - - The Sampling Round can be edited and Samples can be attached - - - Client - LabClerk - LabManager - Manager - Owner - - - Client - LabClerk - LabManager - Manager - Owner - - - - - Client - LabClerk - LabManager - Manager - Owner - - - Analyst - Client - LabClerk - LabManager - Manager - Owner - RegulatoryInspector - Verifier - - - - - Close - - senaite.core: Transition: Close Sampling Round - python:here.workflow_guard_close() if hasattr(here, 'workflow_guard_close') else True - - - - - Open - - senaite.core: Transition: Reopen Sampling Round - python:here.workflow_guard_open() if hasattr(here, 'workflow_guard_open') else True - - - - - Previous transition - - transition/getId|nothing - - - - - - - The ID of the user who performed the last transition - - user/getId - - - - - - - Comment about the last transition - - python:state_change.kwargs.get('comment', '') - - - - - - - Provides access to workflow history - - state_change/getHistory - - - - - - - When the previous transition was performed - - state_change/getDateTime - - - - - - diff --git a/bika/lims/setuphandlers.py b/bika/lims/setuphandlers.py index 0b2f95908d..2a5305c5c0 100644 --- a/bika/lims/setuphandlers.py +++ b/bika/lims/setuphandlers.py @@ -117,7 +117,6 @@ ("Preservation", ["bika_setup_catalog"]), ("ReferenceDefinition", ["bika_setup_catalog", "portal_catalog"]), ("ReferenceSample", ["bika_catalog", "portal_catalog"]), - ("SRTemplate", ["bika_setup_catalog", "portal_catalog"]), ("SampleCondition", ["bika_setup_catalog"]), ("SampleMatrix", ["bika_setup_catalog"]), ("SamplePoint", ["bika_setup_catalog", "portal_catalog"]), diff --git a/bika/lims/skins/bika/bika_widgets/srtemplateartemplateswidget.pt b/bika/lims/skins/bika/bika_widgets/srtemplateartemplateswidget.pt deleted file mode 100644 index ccb088cfa4..0000000000 --- a/bika/lims/skins/bika/bika_widgets/srtemplateartemplateswidget.pt +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - -
- - -
-
- -
-
- - - diff --git a/bika/lims/subscribers/configure.zcml b/bika/lims/subscribers/configure.zcml index 16bf26c8c4..292673f9e0 100644 --- a/bika/lims/subscribers/configure.zcml +++ b/bika/lims/subscribers/configure.zcml @@ -79,12 +79,6 @@ handler="bika.lims.subscribers.analysis.ObjectRemovedEventHandler" /> - -