Skip to content

Commit

Permalink
feat: expiration date and storage temperature fields in inventory (#2152
Browse files Browse the repository at this point in the history
)


* allow import of storage temperature for chemicals

*  rearrange chemical fields in inventory tab
  • Loading branch information
adambasha0 authored Nov 15, 2024
1 parent 8907b90 commit 9c3239f
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 50 deletions.
18 changes: 11 additions & 7 deletions app/assets/stylesheets/legacy/chemical-tab.scss
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,11 @@ table.table-borderless {
}

.inventory-information-status {
width: 22%;
width: 28%;
}

.inventory-text-input {
width: 19%;
width: 30%;
}

.text-input-group {
Expand All @@ -144,20 +144,24 @@ table.table-borderless {
}

.text-input-price {
width: 22%;
width: 10%;
}

.text-input-person {
width: 22%;
width: 15%;
}

.text-input-storage-temperature {
width: 39%;
}

.text-input-date {
margin-top: -17px;
width: 35%;
margin-top: -17px;
width: 65%;
}

.text-input-required-by {
width: 22%;
width: 18%;
}
}

Expand Down
6 changes: 4 additions & 2 deletions app/packs/src/apps/mydb/elements/details/NumericInputUnit.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ export default function NumericInputUnit(props) {
convertedValue = parseFloat(value);
break;
}
onInputChange(convertedValue, convertedUnit);
setUnit(convertedUnit);
if (!Number.isNaN(convertedValue)) {
onInputChange(convertedValue, convertedUnit);
setUnit(convertedUnit);
}
};

const handleInputValueChange = (event) => {
Expand Down
63 changes: 42 additions & 21 deletions app/packs/src/components/ChemicalTab.js
Original file line number Diff line number Diff line change
Expand Up @@ -395,26 +395,32 @@ export default class ChemicalTab extends React.Component {
}

textInput(data, label, parameter) {
const componentClass = parameter !== 'important_notes' && parameter !== 'disposal_info' && parameter !== 'sensitivity_storage'
const componentClass = parameter !== 'important_notes'
&& parameter !== 'disposal_info' && parameter !== 'sensitivity_storage'
&& parameter !== 'solubility' ? 'input' : 'textarea';
let value = '';
if (parameter !== 'cas') {
value = data?.[parameter] ?? '';
} else {
value = data || '';
}
let conditionalOverlay;
if (parameter === 'date') {
conditionalOverlay = 'please enter the name of the person who orders/ordered the substance';
let conditionalOverlay = null;
if (parameter === 'person') {
conditionalOverlay = 'please enter the name of the person who ordered the substance';
} else if (parameter === 'required_by') {
conditionalOverlay = 'please enter the name of the person who requires the substance';
} else {
conditionalOverlay = null;
} else if (parameter === 'expiration_date') {
conditionalOverlay = 'please enter the expiration date of the substance';
}
const checkLabel = label !== 'Date' && <Form.Label>{label}</Form.Label>;
const dateArray = ['person', 'required_by', 'expiration_date'];

return (
<OverlayTrigger placement="top" overlay={parameter === 'date' || parameter === 'required_by' ? <Tooltip id="field-text-input">{conditionalOverlay}</Tooltip> : <div />}>
<OverlayTrigger
placement="top"
overlay={dateArray.includes(parameter)
? <Tooltip id="field-text-input">{conditionalOverlay}</Tooltip> : <div />}
>
<Form.Group>
{checkLabel}
<Form.Control
Expand Down Expand Up @@ -496,14 +502,17 @@ export default class ChemicalTab extends React.Component {
}

numInputWithoutTable(data, label, parameter) {
const value = data?.[parameter]?.value ?? 0;
const value = data?.[parameter]?.value;
let unit; let field;
if (parameter === 'amount') {
unit = data?.[parameter]?.unit ?? 'mg';
field = 'chemical_amount_in_g';
} else if (parameter === 'volume') {
unit = data?.[parameter]?.unit ?? 'ml';
field = 'chemical_amount_in_l';
} else if (parameter === 'storage_temperature') {
unit = data?.[parameter]?.unit ?? '°C';
field = 'storage_temperature';
}
return (
<NumericInputUnit
Expand Down Expand Up @@ -892,21 +901,15 @@ export default class ChemicalTab extends React.Component {
<Col>
{this.textInput(data, 'Order number', 'order_number')}
</Col>
<Col>
{this.numInputWithoutTable(data, 'Amount', 'amount')}
</Col>
<Col className="pt-2">
{this.numInputWithoutTable(data, '', 'volume')}
</Col>
</Row>
<Row>
<Col sm={3}>
{this.textInput(data, 'Price', 'price')}
</Col>
<Col sm={3}>
</Row>
<Row className="mb-3">
<Col>
{this.textInput(data, 'Person', 'person')}
</Col>
<Col sm={3}>
<Col sm={4}>
<ButtonGroup className="mb-2">
<ButtonGroupToggleButton
onClick={() => this.setState({ switchRequiredOrderedDate: 'required' })}
Expand All @@ -922,15 +925,33 @@ export default class ChemicalTab extends React.Component {
>
Ordered date
</ButtonGroupToggleButton>
<ButtonGroupToggleButton
onClick={() => this.setState({ switchRequiredOrderedDate: 'expiration' })}
active={switchRequiredOrderedDate === 'expiration'}
size="xxsm"
>
Expiration date
</ButtonGroupToggleButton>
</ButtonGroup>
{switchRequiredOrderedDate === 'required'
? this.textInput(data, 'Date', 'required_date')
: this.textInput(data, 'Date', 'ordered_date')}
{switchRequiredOrderedDate === 'required' && this.textInput(data, 'Date', 'required_date')}
{switchRequiredOrderedDate === 'ordered' && this.textInput(data, 'Date', 'ordered_date')}
{switchRequiredOrderedDate === 'expiration' && this.textInput(data, 'Date', 'expiration_date')}
</Col>
<Col sm={3}>
{this.textInput(data, 'Required by', 'required_by')}
</Col>
</Row>
<Row className="mb-3">
<Col>
{this.numInputWithoutTable(data, 'Amount', 'amount')}
</Col>
<Col className="pt-2">
{this.numInputWithoutTable(data, '', 'volume')}
</Col>
<Col>
{this.numInputWithoutTable(data, 'Storage Temperature', 'storage_temperature')}
</Col>
</Row>
</>
);
}
Expand Down
9 changes: 7 additions & 2 deletions app/packs/src/components/contextActions/ModalExport.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,16 @@ export default class ModalExport extends React.Component {
{ value: 'person', text: 'person', checked: false },
{ value: 'required_date', text: 'required date', checked: false },
{ value: 'ordered_date', text: 'ordered date', checked: false },
{ value: 'expiration_date', text: 'expiration date', checked: false },
{ value: 'storage_temperature', text: 'storage temperature', checked: false },
{ value: 'required_by', text: 'required by', checked: false },
{
value: ['safety_sheet_link_merck', 'safety_sheet_link_thermofischer'],
value: [
'safety_sheet_link_merck',
'safety_sheet_link_thermofischer'
],
text: 'safety sheet link',
checked: false
checked: false,
},
{ value: ['product_link_merck', 'product_link_thermofischer'], text: 'product link', checked: false },
{ value: 'pictograms', text: 'pictograms', checked: false },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ export default {
table: 'chemicals',
type: 'text',
},
{
column: 'expiration_date',
label: 'Expiration date',
key: 'information',
table: 'chemicals',
type: 'text',
},
{
column: 'required_by',
label: 'Required by',
Expand Down
29 changes: 17 additions & 12 deletions lib/export/export_chemicals.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
module Export
class ExportChemicals
CHEMICAL_FIELDS = %w[
chemical_sample_id cas status vendor order_number amount price person required_date
ordered_date required_by pictograms h_statements p_statements safety_sheet_link_merck
safety_sheet_link_thermofischer product_link_merck product_link_thermofischer
host_building host_room host_cabinet host_group owner borrowed_by current_building
current_room current_cabinet current_group disposal_info important_notes
chemical_sample_id cas status vendor order_number amount price person required_date owner
ordered_date expiration_date storage_temperature required_by pictograms h_statements
p_statements safety_sheet_link_merck safety_sheet_link_thermofischer product_link_merck
product_link_thermofischer host_building host_room host_cabinet host_group important_notes
borrowed_by current_building current_room current_cabinet current_group disposal_info
].freeze
MERCK_SDS_LINK = 'c."chemical_data"->0->\'merckProductInfo\'->\'sdsLink\''
ALFA_SDS_LINK = 'c."chemical_data"->0->\'alfaProductInfo\'->\'sdsLink\''
Expand All @@ -22,6 +22,8 @@ class ExportChemicals
amount: ['c."chemical_data"->0->\'amount\'', '"amount"', nil],
order_number: ['c."chemical_data"->0->\'order_number\'', '"order_number"', nil],
required_date: ['c."chemical_data"->0->\'required_date\'', '"required_date"', nil],
expiration_date: ['c."chemical_data"->0->\'expiration_date\'', '"expiration_date"', nil],
storage_temperature: ['c."chemical_data"->0->\'storage_temperature\'', '"storage_temperature"', nil],
required_by: ['c."chemical_data"->0->\'required_by\'', '"required_by"', nil],
safety_sheet_link_merck: [MERCK_SDS_LINK, '"safety_sheet_link_merck"', nil],
safety_sheet_link_thermofischer: [ALFA_SDS_LINK, '"safety_sheet_link_thermofischer"', nil],
Expand Down Expand Up @@ -67,8 +69,9 @@ def self.format_chemical_results(result)
end

def self.construct_column_name(column_name, index, columns_index)
format_chemical_column = ['p statements', 'h statements', 'amount', 'safety sheet link thermofischer',
'safety sheet link merck', 'product link thermofischer', 'product link merck'].freeze
format_chemical_column = ['p statements', 'h statements', 'amount', 'storage temperature',
'safety sheet link thermofischer', 'safety sheet link merck',
'product link thermofischer', 'product link merck'].freeze
if column_name.is_a?(String) && CHEMICAL_FIELDS.include?(column_name)
column_name = column_name.tr('_', ' ')
construct_column_name_hash(columns_index, column_name, index) if format_chemical_column.include?(column_name)
Expand All @@ -86,6 +89,8 @@ def self.construct_column_name_hash(columns_index, column_name, index)
columns_index['h_statements'] = index
when 'amount'
columns_index['amount'] = index
when 'storage temperature'
columns_index['storage_temperature'] = index
when 'safety sheet link merck', 'safety sheet link thermofischer'
columns_index['safety_sheet_link'].push(index)
when 'product link merck', 'product link thermofischer'
Expand All @@ -110,8 +115,8 @@ def self.format_row(row, columns_index, indexes_to_delete)
case index
when columns_index['p_statements'], columns_index['h_statements']
value = format_p_and_h_statements(value)
when columns_index['amount']
value = format_chemical_amount(value)
when columns_index['amount'], columns_index['storage_temperature']
value = format_chemical_fields_with_unit(value)
when columns_index['safety_sheet_link'][0]
value = format_link(value, row, columns_index['safety_sheet_link'][1], indexes_to_delete)
when columns_index['product_link'][0]
Expand All @@ -126,9 +131,9 @@ def self.format_p_and_h_statements(value)
keys.join('-')
end

def self.format_chemical_amount(value)
amount_value_unit = JSON.parse(value).values
sorted = amount_value_unit.sort_by { |element| [element.is_a?(Integer) || element.is_a?(Float) ? 0 : 1, element] }
def self.format_chemical_fields_with_unit(value)
field_values = JSON.parse(value).values
sorted = field_values.sort_by { |element| [element.is_a?(Integer) || element.is_a?(Float) ? 0 : 1, element] }
sorted.join
end

Expand Down
32 changes: 28 additions & 4 deletions lib/import/import_chemicals.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ module Import
class ImportChemicals
SAFETY_PHRASES = %w[pictograms h_statements p_statements].freeze
AMOUNT = %w[amount].freeze
AMOUNT = %w[amount].freeze
STORAGE_TEMPERATURE = %w[storage_temperature].freeze
SAFETY_SHEET = %w[safety_sheet_link_merck product_link_merck].freeze
KEYS_TO_EXCLUDE = SAFETY_SHEET + %w[cas].freeze
SIGMA_ALDRICH_PATTERN = /(sigmaaldrich|merck)/.freeze
Expand All @@ -17,7 +19,7 @@ class ImportChemicals
'cas', 'status', 'vendor', 'order number', 'amount', 'price', 'person', 'required date', 'ordered date',
'required by', 'pictograms', 'h statements', 'p statements', 'safety sheet link', 'product link', 'host building',
'host room', 'host cabinet', 'host group', 'owner', 'borrowed by', 'current building', 'current room',
'current cabinet', 'current group', 'disposal info', 'important notes'
'current cabinet', 'current group', 'disposal info', 'important notes', 'expiration date'
].freeze
GHS_VALUES = %w[GHS01 GHS02 GHS03 GHS04 GHS05 GHS06 GHS07 GHS08 GHS09].freeze
AMOUNT_UNITS = %w[g mg μg].freeze
Expand Down Expand Up @@ -50,14 +52,25 @@ def self.process_column(chemical, column_header, value)
map_column = CHEMICAL_FIELDS.find { |e| e == column_header.downcase.rstrip }
key = to_snake_case(column_header)
format_value = value.strip
if map_column.present? && should_process_key(key)
chemical['chemical_data'][0][key] = format_value
elsif SAFETY_SHEET.include?(key)

return process_chemical_data(chemical, key, format_value) if map_column.present? && should_process_key(key)

process_special_fields(chemical, key, format_value)
end

def self.process_chemical_data(chemical, key, format_value)
chemical['chemical_data'][0][key] = format_value
end

def self.process_special_fields(chemical, key, format_value)
if SAFETY_SHEET.include?(key)
set_safety_sheet(chemical, key, format_value)
elsif SAFETY_PHRASES.include?(key)
set_safety_phrases(chemical, key, format_value)
elsif AMOUNT.include?(key)
set_amount(chemical, format_value)
elsif STORAGE_TEMPERATURE.include?(key)
set_storage_temperature(chemical, format_value)
end
end

Expand Down Expand Up @@ -168,5 +181,16 @@ def self.set_amount(chemical, value)
chemical['chemical_data'][0]['amount']['value'] = quantity
chemical['chemical_data'][0]['amount']['unit'] = unit
end

def self.set_storage_temperature(chemical, value)
unit_is_celsius = value.gsub(/\d+(\.\d+)?/, '') == '°C'
return chemical unless unit_is_celsius

if chemical['chemical_data'][0]['storage_temperature'].nil?
chemical['chemical_data'][0]['storage_temperature'] = {}
end
chemical['chemical_data'][0]['storage_temperature']['value'] = value.to_f
chemical['chemical_data'][0]['storage_temperature']['unit'] = '°C'
end
end
end
10 changes: 8 additions & 2 deletions spec/lib/export/export_chemicals_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@
# rubocop: disable Style/OpenStructUse

describe Export::ExportChemicals do
describe '.format_chemical_amount' do
describe '.format_chemical_fields_with_unit' do
it 'formats chemical amount correctly' do
input_value = '{"value": 50, "unit": "mg"}'
formatted_amount = described_class.format_chemical_amount(input_value)
formatted_amount = described_class.format_chemical_fields_with_unit(input_value)
expect(formatted_amount).to eq('50mg')
end

it 'formats chemical storage temperature correctly' do
input_value = '{"value": 30, "unit": "°C"}'
formatted_amount = described_class.format_chemical_fields_with_unit(input_value)
expect(formatted_amount).to eq('30°C')
end
end

describe '.format_columns_name' do
Expand Down

0 comments on commit 9c3239f

Please sign in to comment.