mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-09-28 19:06:18 +08:00
81a9a7225b
* Add initial implementation of inventory stock management [SCI-6402]
* Add stock column type (#3786)
* Add stock column type
* Create new stock column [SCI-6410]
* Small fixed for stock column [SCI-6410]
* Add stock column validations [SCI-6410]
Co-authored-by: Anton <anton@scinote.net>
* Add stock table renders [SCI-6412] (#3787)
Co-authored-by: Anton <anton@scinote.net>
* Implemented stock management modal [SCI-6417] (#3788)
* Implement inventory stock management modal [SCI-6417]
* Add generalized validation mechanic, some bugfixes [SCI-6417]
* Fix permission check and method name in RepositoryStockValue [SCI-6417]
* Add stock and consumption to assigned items section [SCI-6434] (#3793)
* Added UPDATE_STOCK_CONSUMPTION to MyModule permissons [SCI-6418] (#3781)
* Fix invalid return in reports jobs [SCI-6409] (#3777)
* Added UPDATE_STOCK_CONSUMPTION to MyModule permissons [SCI-6418]
* Add current/new amount section to stock [SCI-6416] (#3791)
Co-authored-by: Anton <anton@scinote.net>
* Task stock consumption modal[SCI-6444][SCI-6445] (#3798)
Add main logic for consumption on task [SCI-6444]
Co-authored-by: Anton <anton@scinote.net>
* Add stock management columns to snapshots [SCI-6448]
* Handle stock management in full table views [SCI-6440]
* Implement stock management activities [SCI-6452] (#3810)
* Implement stock management activities [SCI-6452]
* PR code fixes [SCI-6452]
* Implement import for repository stock values [SCI-6461] (#3818)
* Add permissions checking to assigned items view on tasks [SCI-6435] (#3801)
* Add front-end validation for comments field [SCI-6464] (#3829)
Co-authored-by: Anton <anton@scinote.net>
* Add stock consumption to pdf and docx [SCI-6460] (#3816)
Co-authored-by: Anton <anton@scinote.net>
* Add support of repository snapshots to assigned items section [SCI-6439] (#3828)
* Change subject of Repository (#3838)
* Fixed full view assigned items modal stock consumption (#3846)
* Implement repository snapshots displaying on assigned items full view modal [SCI-6442] (#3862)
* Implement low stock threshold column [SCI-6555] (#3907)
* Stock column fixes [SCI-6455] (#3878)
* Fix issues with stock column management [SCI-6455]
* Refactor stock column in datatables [SCI-6455]
* Fix tests [SCI-6486] (#3913)
* Fix tests [SCI-6486]
* Fix rspec tests [SCI-6486]
Co-authored-by: Anton <anton@scinote.net>
* Implement basic logic for Date/DateTime/Stock reminders [SCI-6554] (#3911)
* Implement basic logic for Date/DateTime/Stock reminders [SCI-6554]
* Implement bell icon [SCI-6500]
* Refactor reminder cells scope [SCI-6554]
* Add red dot for date/datetime reminder [SCI-6499] (#3924)
Co-authored-by: Anton <anton@scinote.net>
* Add reminders to stock modal [SCI-6557] (#3917)
Co-authored-by: Anton <anton@scinote.net>
* Add flyout for repository reminders [SCI-6501] (#3926)
Co-authored-by: Anton <anton@scinote.net>
* Fix moving experiment [SCI-6602] (#3927)
* Update Rails to 6.1.4.7 [SCI-6615] (#3928)
* Task inventory activity for assigned item consumption [SCI-6453] (#3830)
* Add task inventory activity [SCI-6453]
* Apply user's time zone in advanced filters for time data type [SCI-6585] (#3930)
* Bump version to 1.24.2
* Implement hidden repository cell reminders [SCI-6504] (#3933)
* Low stock flyout reminders [SCI-6502] (#3932)
* Display low stock flyout reminder [SCI-6502]
* Display low stock flyout reminder [SCI-6502]
* Adapt showing stock reminders for every bell icon click [SCI-6502]
* Correct hound error [SCI-6502]
* Fix event registration for fetching reminder data [SCI-6502]
* Fix event registration for fetching reminder data [SCI-6502]
* Fix hound [SCI-6502]
* Remove not needed line [SCI-6502]
* Add reminder template [SCI-6502]
* Add clearing messages [SCI-6502]
* Displaying low stock warning [SCI-6497] (#3912)
* Low stock warning [SCI-6497
* Fix some bugs [SCI-6497]
* Fix to long line [SCI-6497]
* Clean not needed information in renderes [SCI-6497]
* Icon bell reminder for an assigned item on the task [SCI-6506] (#3929)
* Add bell icon on assigned task [SCI-6506]
* Add flyout and improve quering [SCI-6506]
* Refactor repository toolbar [SCI-6545] (#3943)
Co-authored-by: Anton <anton@scinote.net>
* Add datetime reminders to columns modal [SCI-6556] (#3934)
Co-authored-by: Anton <anton@scinote.net>
* Hide reminders for archived repositories [SCI-6609] (#3941)
* Hide reminders for archived repositories [SCI-6609]
* Always pass repository in datatable helper [SCI-6609]
* Handle locked stock consumption state [SCI-6608] (#3942)
* Change env variable name for s3 bucket region [SCI-6603] (#3944)
* Add last_transition_error column to tasks [SCI-6610] (#3949)
* Add microtransactions to stock consumptions [SCI-6626] (#3948)
Co-authored-by: Anton <anton@scinote.net>
* Date remidner flyout [SCI-6503] (#3937)
* Implement date reminder flyout [SCI-6503]
* Show only days left for date reminder [SCI-6503]
* Pluralize day in reminders [SCI-6503]
* Create partials for different reminders [SCI-6503]
* Unify css for reminder [SCI-6503]
* Add micro interactions for stock modal [SCI-6625] (#3947)
Co-authored-by: Anton <anton@scinote.net>
* Hide options to add New Tags for users without permissions on Task level [SCI-6573] (#3945)
* Bump lodash-es from 4.17.15 to 4.17.21 (#3939)
Bumps [lodash-es](https://github.com/lodash/lodash) from 4.17.15 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.21)
---
updated-dependencies:
- dependency-name: lodash-es
dependency-type: indirect
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Implement clearing hidden repository reminders [SCI-6507] (#3936)
* Add stock filters [SCI-6547] (#3938)
Co-authored-by: Anton <anton@scinote.net>
* Fix assign view for task repository [SCI-6648] (#3954)
Co-authored-by: Anton <anton@scinote.net>
* Add micro-interactions to reminders flyout [SCI-6627] (#3951)
Co-authored-by: Anton <anton@scinote.net>
* Improve error reporting in task status transition [SCI-6611] (#3952)
* Add ordering to global search results [SCI-6639] (#3960)
* Fix multiple stock bugs [SCI-6651] (#3959)
Co-authored-by: Anton <anton@scinote.net>
* Fix large previews for csv files [SCI-6619] (#3961)
* Add alias to cell sort query, to prevent join conflicts [SCI-6649] (#3953)
* Add alias to cell sort query, to prevent join conflicts [SCI-6649]
* Added value_type to join condition to make use of DB index [SCI-6649]
* Update front end validation for columns managment [SCI-6657] (#3962)
Co-authored-by: Anton <anton@scinote.net>
* Print protocol smart annotation and table improvements [SCI-6566] (#3925)
* Improve table printing in the print menu [SCI-6566]
* Open smart annotation in new tab for print view [SCI-6566]
* Unify naming of same parameter [SCI-6566]
* Fix typo [SCI-6566]
* Fix hound errors [SCI-6566]
* Add stock management toggling [SCI-6653] (#3967)
Co-authored-by: Anton <anton@scinote.net>
* Fix caching of an experiment card dropdown [SCI-6606] (#3963)
* Add stock consumption permission to user roles [SCI-6665] (#3966)
* Show archive icon only on archived projects in the header [SCI-6617] (#3965)
* Fix assigned items fullview modal [SCI-6664] (#3968)
* Implement hide all repository reminders button [SCI-6505] (#3940)
* Viewer role does not see any tasks in archived project [SCI-6616] (#3958)
* Fix viewer role not see any tasks in archived project [SCI-6616]
* Fix rollback for add read archive permission migration [SCI-6616]
* Stock modal bugs [SCI-6667] (#3970)
Co-authored-by: Anton <anton@scinote.net>
* Always use Tika text extractor in server mode [SCI-6658] (#3957)
* Implement stock consumption via the API [SCI-6642] (#3964)
* Implement stock consumption via the API [SCI-6642]
* Remove unnecessary attribute from InventoryItemSerializer [SCI-6642]
* Amend permission check, add nested transaction support to consume_stock method [SCI-6642]
* Toolbar fixes [SCI-6670] (#3973)
Co-authored-by: Anton <anton@scinote.net>
* Make stock column work properly with different orders [SCI-6677] (#3974)
* Fix filters loading for stock filter [SCI-6687] (#3975)
Co-authored-by: Anton <anton@scinote.net>
* Hide reminders and disable stock consumption for archived items [SCI-6689] (#3978)
* Fix red dot for datetime columns [SCI-6684] (#3977)
Co-authored-by: Anton <anton@scinote.net>
* Fix saving of inventory date time reminders saving [SCI-6672] (#3976)
* Bump puma from 5.6.2 to 5.6.4 (#3972)
Bumps [puma](https://github.com/puma/puma) from 5.6.2 to 5.6.4.
- [Release notes](https://github.com/puma/puma/releases)
- [Changelog](https://github.com/puma/puma/blob/master/History.md)
- [Commits](https://github.com/puma/puma/compare/v5.6.2...v5.6.4)
---
updated-dependencies:
- dependency-name: puma
dependency-type: direct:production
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Don't load reminders if the stock feature is disabled [SCI-6673] (#3981)
* Don't load reminders if the stock feature is disabled [SCI-6673]
* Don't load reminders if the stock feature is disabled [SCI-6673]
* Unify stock management enabled check [6673]
* Update repository card view for stock [SCI-6685] (#3982)
Co-authored-by: Anton <anton@scinote.net>
* Disable stock managememnt for all tables in my module context [SCI-6692] (#3983)
* Implement failed snapshot pop-up on task screen [SCI-6612] (#3950)
* Implement failed snapshot pop-up on task screen [SCI-6612]
* Copy change [SCI-6612]
* Proper handling of snapshot transition error [SCI-6612]
* Move modal auto open logic to JS file [SCI-6612]
* Remove unnecessary .html_safe [SCI-6612]
* Fix assigning and consuming items [SCI-6686] (#3985)
* Repository toolbar CSS fixes [SCI-6676] (#3984)
Co-authored-by: Anton <anton@scinote.net>
* Add basic validation to reminder value to prevent integer overflow errors [SCI-6693] (#3986)
* Fix reminder dropdown on task screen [SCI-6678] (#3987)
Co-authored-by: Anton <anton@scinote.net>
* Fix inventory sorting with date time reminders [SCI-6683] (#3980)
* Fix css stock modal [SCI-6675] (#3989)
Co-authored-by: Anton <anton@scinote.net>
* Stock column management UX/UI fixes [SCI-6674] (#3979)
* Fix red dot for dates in repository [SCI-6696] (#3991)
Co-authored-by: Anton <anton@scinote.net>
* Added styling for failed snapshots in sidebar [SCI-6636] (#3990)
* Added styling for failed snapshots in sidebar [SCI-6636]
* Simplify markup for failed icon [SCI-6636]
* Turn off autocomplete for stock amount/reminder [SCI-6694] (#3988)
* Override error styling in stock column management [SCI-6674] (#3995)
* Fix repository full view tables without stock management [SCI-6703] (#3994)
* Add pagination to projects list [SCI-6655]
* Add reminder preset to date(time) reminders [SCI-6693] (#3996)
* Fix color on consumption link [SCI-6686] (#3992)
* Fix sorting by date time columns in inventories [SCI-6683] (#4002)
* Improve loading of the dashboard [SCI-6618] (#4001)
* Stock modal UX fixes [SCI-6714] (#3998)
Co-authored-by: Anton <anton@scinote.net>
* Fix css for stotck modal [SCI-6698] (#3999)
Co-authored-by: Anton <anton@scinote.net>
* API: add endpoint for updating of stock [SCI-6549] (#3955)
* Add test for Stock repository cell [SCI-6549]
* Create and update stock inventory cell [SCI-6549]
* Fix hound errors [SCI-6549]
* Fix ledger recording [SCI-6549]
* Fix api endpoint [SCI-6549]
* Fix hound [SCI-6549]
* Fix collapsing of assigned items tables [SCI-6705] (#4000)
* API: add endpoint for creating stock column [SCI-6550] (#3956)
* Add test for repositoty stock column api [SCI-6550]
* Create and update stock column [SCI-6550]
* Change stock unit [SCI-6550]
* Fix hound [SCI-6550]
* Fix on delete [SCI-6550]
* Fix houd [SCI-6550]
* Removed autofocus clear on open reminder flyout [SCI-6690] (#4003)
* Removed clear autofocus on open reminder flyout [SCI-6690]
* Fix hound [SCI-6690]
* Adding/changing stock consumption [SCI-6708] (#4005)
* Adding/changing stock consumption [SCI-6708]
* Fix hound [SCI-6708]
* Remove date red dots for snapshots [SCI-6715] (#4004)
Co-authored-by: Anton <anton@scinote.net>
* Add snapshot error message below task status [SCI-6614] (#4009)
* Add repository snapshot error modal [SCI-6613] (#3993)
* Bump nokogiri from 1.13.3 to 1.13.4 (#4008)
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.13.3 to 1.13.4.
- [Release notes](https://github.com/sparklemotion/nokogiri/releases)
- [Changelog](https://github.com/sparklemotion/nokogiri/blob/v1.13.4/CHANGELOG.md)
- [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.13.3...v1.13.4)
---
updated-dependencies:
- dependency-name: nokogiri
dependency-type: direct:production
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Add pagination for experiments [SCI-6656]
* Fix sorting by time and time range columns [SCI-6683] (#4011)
* Bump moment from 2.24.0 to 2.29.2 (#4006)
Bumps [moment](https://github.com/moment/moment) from 2.24.0 to 2.29.2.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.24.0...2.29.2)
---
updated-dependencies:
- dependency-name: moment
dependency-type: direct:production
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Align items in assigned item section [SCI-6707] (#4007)
* Add locking and unique index to repository row assigning [SCI-6591] (#3921)
* tmp (#3935)
* Revert "tmp (#3935)" (#4014)
This reverts commit 043086d55f
.
* Move cursor to end of value when focusing consumption amount [SCI-6727] (#4013)
* Fix removing stock reminder threshold [SCI-6724] (#4010)
* Stock small ux fixes [SCI-6714] (#4015)
Co-authored-by: Anton <anton@scinote.net>
* Add aibility to delete stock column [SCI-6723] (#4017)
Co-authored-by: Anton <anton@scinote.net>
* Fix red dot for date reminders [SCI-6696] (#4016)
Co-authored-by: Anton <anton@scinote.net>
* Change the way setting stock works [SCI-6730] (#4018)
* Fix error modal opening on successful snapshot [SCI-6726] (#4019)
* Refactor and fix display of stock warnings and stock consumption [SCI-6734] (#4021)
* Refactor and fix how stock consumption is displayed [SCI-6734]
* Refactor and fix display of stock warnings [SCI-6734]
* Fix stock consumption in reports [SCI-6735]
* Fix markup
* Focus authenticator code field [SCI-6716] (#4022)
* Hide reminders settings and red dots if stock is disabled [SCI-6673] (#4024)
* Fix decimals in stock consumption modal [SCI-6732]
* Add edit title for stock consumption modal [SCI-6731]
* Highlight negative stock in modal with red [SCI-6729]
* Stock management test [SCI-6420] (#3946)
* Initial test for stock management
* Repository stock values adding [does not work] SCI-6420
* Fix typos SCI-6420
* Fix test [SCI-6420]
* Test changes [SCI-6402]
* Remove locking test [SCI-6420]
* Remove lock [SCI-6420]
* Remove serializer [SCI-6420]
* Fix stock test and add ledger creation on consume [SCI-6420]
* Fix inviting users to team [SCI-6725] (#4026)
* Improve stock ledger records creation [SCI-6419]
* Fix stock modal add/remove value preset value [SCI-6740]
* API GET repository stock column output fix [SCI-6550] (#4030)
* Add include stock unit items to Stock column get [SCI-6550]
* Fix stock column test [SCI-6550]
* Fix hound [SCI-6550]
* Move list-type column includes to param, unify naming [SCI-6738] (#4036)
* Add default includes for inventory columns with lists [SCI-6738]
* Move list-type column includes to param, unify naming [SCI-6738]
* Fix snapshot consumption display [SCI-6734] (#4035)
* Fix decimal render function [SCI-6742] (#4037)
Co-authored-by: Anton <anton@scinote.net>
* Add comment to repository stock activities [SCI-6746]
* Fix default stock column default units selection [SCI-6744]
* Add negative validation for stock [SCI-6743]
* Highlight negative value in consumption modal [SCI-6741]
* Fix snapshot creation with stock consumption [SCI-6762]
* Update stock value without reloading the table [SCI-6745] (#4041)
* Allow tag creation on task level if you have permission [SCI-6573] (#4031)
* Enable team normal user to edit repository files [SCI-6765] (#4049)
* Add negative validation for treshold [SCI-6743]
* Copy fix [SCI-6762] (#4048)
* Add bell icon for negative stock [SCI-6770]
* Fix formatting of stock consumption on tasks [SCI-6737] (#4050)
* Fix duplicated inventories on tasks for export all [SCI-6776]
* Stock / stock consumption display fixes [SCI-6771] (#4054)
* Fix blank stock consumption representation in reports [SCI-6769]
* Upgrade Rails to 6.1.5.1
* Show last page message only after second page [SCI-6761]
* Small CSS fixes for repository [SCI-6767]
* Added validations for date(time) column reminder [SCI-6775] (#4063)
* Upgrade Ruby to 2.7.6
* Open repository on print view [SCI-6566] (#4055)
* Fix saving of new date time columns with reminders [SCI-6774] (#4068)
* Improve input field for adding new team [SCI-6155]
* Allow deleteion of stock columns when stock management is disabled [SCI-6800]
* Update default label template [SCI-6763] (#4064)
* Stock editing and reminder fixes [SCI-6803] (#4078)
* Fix stock editing after adding new value [SCI-6803]
* Don't load reminders for snapshots [SCI-6803]
* Improve loading time of canvas view/edit [SCI-6797]
* Fix stock consumption rounding [SCI-6807]
* Fix displaying of stock consumption units [SCI-6795]
* Fix task dropdown actions [SCI-6817]
* Fix archived tasks view [SCI-6822]
* Fix display of repository snapshot with stock consumption [SCI-6824]
* Fix duplicated counters on task card [SCI-6825]
* Bump version to 1.25.0
Co-authored-by: Oleksii Kriuchykhin <okriuchykhin@biosistemika.com>
Co-authored-by: aignatov-bio <47317017+aignatov-bio@users.noreply.github.com>
Co-authored-by: Anton <anton@scinote.net>
Co-authored-by: ajugo <andrej.jugovic7@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
541 lines
19 KiB
Ruby
541 lines
19 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class MyModule < ApplicationRecord
|
|
SEARCHABLE_ATTRIBUTES = ['my_modules.name', 'my_modules.description']
|
|
|
|
include ActionView::Helpers::NumberHelper
|
|
include ArchivableModel
|
|
include SearchableModel
|
|
include SearchableByNameModel
|
|
include TinyMceImages
|
|
include PermissionCheckableModel
|
|
include Assignable
|
|
|
|
attr_accessor :transition_error_rollback
|
|
|
|
enum state: Extends::TASKS_STATES
|
|
|
|
before_validation :archiving_and_restoring_extras, on: :update, if: :archived_changed?
|
|
before_save -> { report_elements.destroy_all }, if: -> { !new_record? && experiment_id_changed? }
|
|
around_save :exec_status_consequences, if: :my_module_status_id_changed?
|
|
before_create :create_blank_protocol
|
|
before_create :assign_default_status_flow
|
|
after_save -> { experiment.workflowimg.purge },
|
|
if: -> { (saved_changes.keys & %w(x y experiment_id my_module_group_id input_id output_id archived)).any? }
|
|
|
|
auto_strip_attributes :name, :description, nullify: false, if: proc { |mm| mm.name_changed? || mm.description_changed? }
|
|
validates :name,
|
|
length: { minimum: Constants::NAME_MIN_LENGTH,
|
|
maximum: Constants::NAME_MAX_LENGTH }
|
|
validates :description, length: { maximum: Constants::RICH_TEXT_MAX_LENGTH }
|
|
validates :x, :y, :workflow_order, presence: true
|
|
validates :experiment, presence: true
|
|
validates :my_module_group, presence: true, if: proc { |mm| !mm.my_module_group_id.nil? }
|
|
validate :coordinates_uniqueness_check, if: :active?
|
|
validates :completed_on, presence: true, if: proc { |mm| mm.completed? }
|
|
|
|
validate :check_status, if: :my_module_status_id_changed?
|
|
validate :check_status_conditions, if: :my_module_status_id_changed?
|
|
validate :check_status_implications
|
|
|
|
belongs_to :created_by, foreign_key: 'created_by_id', class_name: 'User', optional: true
|
|
belongs_to :last_modified_by, foreign_key: 'last_modified_by_id', class_name: 'User', optional: true
|
|
belongs_to :archived_by, foreign_key: 'archived_by_id', class_name: 'User', optional: true
|
|
belongs_to :restored_by, foreign_key: 'restored_by_id', class_name: 'User', optional: true
|
|
belongs_to :experiment, inverse_of: :my_modules, touch: true
|
|
has_one :project, through: :experiment, autosave: false
|
|
belongs_to :my_module_group, inverse_of: :my_modules, optional: true
|
|
belongs_to :my_module_status, optional: true
|
|
belongs_to :changing_from_my_module_status, optional: true, class_name: 'MyModuleStatus'
|
|
delegate :my_module_status_flow, to: :my_module_status, allow_nil: true
|
|
has_many :results, inverse_of: :my_module, dependent: :destroy
|
|
has_many :my_module_tags, inverse_of: :my_module, dependent: :destroy
|
|
has_many :tags, through: :my_module_tags
|
|
has_many :task_comments, foreign_key: :associated_id, dependent: :destroy
|
|
has_many :inputs, class_name: 'Connection', foreign_key: 'input_id', inverse_of: :to, dependent: :destroy
|
|
has_many :outputs, class_name: 'Connection', foreign_key: 'output_id', inverse_of: :from, dependent: :destroy
|
|
has_many :my_modules, through: :outputs, source: :to, class_name: 'MyModule'
|
|
has_many :my_module_antecessors, through: :inputs, source: :from, class_name: 'MyModule'
|
|
has_many :my_module_repository_rows, inverse_of: :my_module, dependent: :destroy
|
|
has_many :repository_rows, through: :my_module_repository_rows
|
|
has_many :repository_snapshots, dependent: :destroy, inverse_of: :my_module
|
|
has_many :user_my_modules, inverse_of: :my_module, dependent: :destroy
|
|
has_many :users, through: :user_assignments
|
|
has_many :designated_users, through: :user_my_modules, source: :user
|
|
has_many :report_elements, inverse_of: :my_module, dependent: :destroy
|
|
has_many :protocols, inverse_of: :my_module, dependent: :destroy
|
|
# Associations for old activity type
|
|
has_many :activities, inverse_of: :my_module
|
|
|
|
scope :overdue, -> { where('my_modules.due_date < ?', Time.current.utc) }
|
|
scope :without_group, -> { active.where(my_module_group: nil) }
|
|
scope :one_day_prior, (lambda do
|
|
where('my_modules.due_date > ? AND my_modules.due_date < ?',
|
|
Time.current.utc,
|
|
Time.current.utc + 1.day)
|
|
end)
|
|
scope :workflow_ordered, -> { order(workflow_order: :asc) }
|
|
scope :uncomplete, -> { where(state: 'uncompleted') }
|
|
|
|
scope :my_module_search_scope, lambda { |experiment_ids, user|
|
|
joins(:user_assignments).where(
|
|
experiment: experiment_ids,
|
|
user_assignments: { user: user }
|
|
).distinct
|
|
}
|
|
|
|
# A module takes this much space in canvas (x, y) in database
|
|
WIDTH = 30
|
|
HEIGHT = 14
|
|
|
|
def self.search(
|
|
user,
|
|
include_archived,
|
|
query = nil,
|
|
page = 1,
|
|
current_team = nil,
|
|
options = {}
|
|
)
|
|
viewable_experiments = Experiment.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT, current_team)
|
|
.pluck(:id)
|
|
|
|
new_query = MyModule.with_granted_permissions(user, MyModulePermissions::READ)
|
|
.where(experiment: viewable_experiments)
|
|
.where_attributes_like(SEARCHABLE_ATTRIBUTES, query, options)
|
|
|
|
new_query = new_query.active unless include_archived
|
|
|
|
# Show all results if needed
|
|
if page == Constants::SEARCH_NO_LIMIT
|
|
new_query
|
|
else
|
|
new_query.limit(Constants::SEARCH_LIMIT).offset((page - 1) * Constants::SEARCH_LIMIT)
|
|
end
|
|
end
|
|
|
|
def self.viewable_by_user(user, teams)
|
|
with_granted_permissions(user, MyModulePermissions::READ)
|
|
.where(experiment: Experiment.viewable_by_user(user, teams))
|
|
end
|
|
|
|
def navigable?
|
|
!experiment.archived? && experiment.navigable?
|
|
end
|
|
|
|
def archived_branch?
|
|
archived? || experiment.archived_branch?
|
|
end
|
|
|
|
def repository_rows_count(repository)
|
|
my_module_repository_rows.joins(repository_row: :repository)
|
|
.where('repositories.id': repository.id)
|
|
.count
|
|
end
|
|
|
|
def assigned_repositories
|
|
team = experiment.project.team
|
|
Repository.accessible_by_teams(team)
|
|
.joins(repository_rows: :my_module_repository_rows)
|
|
.where(my_module_repository_rows: { my_module_id: id })
|
|
.group(:id)
|
|
end
|
|
|
|
def live_and_snapshot_repositories_list
|
|
snapshots = repository_snapshots.left_outer_joins(:original_repository)
|
|
|
|
selected_snapshots = snapshots.where(selected: true)
|
|
.or(snapshots.where(original_repositories_repositories: { id: nil }))
|
|
.or(snapshots.where.not(parent_id: assigned_repositories.select(:id)))
|
|
.select('DISTINCT ON ("repositories"."parent_id") "repositories".*')
|
|
.select('COUNT(repository_rows.id) AS assigned_rows_count')
|
|
.joins(:repository_rows)
|
|
.group(:parent_id, :id)
|
|
.order(:parent_id, updated_at: :desc)
|
|
|
|
live_repositories = assigned_repositories
|
|
.select('repositories.*, COUNT(DISTINCT repository_rows.id) AS assigned_rows_count')
|
|
.where.not(id: repository_snapshots.where(selected: true).select(:parent_id))
|
|
|
|
(live_repositories + selected_snapshots).sort_by { |r| r.name.downcase }
|
|
end
|
|
|
|
def update_report_repository_references(repository)
|
|
ids = if repository.is_a?(Repository)
|
|
RepositorySnapshot.where(parent_id: repository.id).pluck(:id)
|
|
else
|
|
Repository.where(id: repository.parent_id).pluck(:id) +
|
|
RepositorySnapshot.where(parent_id: repository.parent_id).pluck(:id)
|
|
end
|
|
|
|
report_elements.where(repository_id: ids).update(repository: repository)
|
|
end
|
|
|
|
def undesignated_users
|
|
User.joins(:user_assignments)
|
|
.joins(
|
|
"LEFT OUTER JOIN user_my_modules ON user_my_modules.user_id = users.id "\
|
|
"AND user_my_modules.my_module_id = #{id}"
|
|
)
|
|
.where(user_assignments: { assignable: self })
|
|
.where(user_my_modules: { id: nil })
|
|
.distinct
|
|
end
|
|
|
|
def unassigned_tags
|
|
Tag.find_by_sql(
|
|
"SELECT DISTINCT tags.id, tags.name, tags.color FROM tags " +
|
|
"INNER JOIN experiments ON experiments.project_id = tags.project_id " +
|
|
"WHERE experiments.id = #{experiment_id.to_s} AND tags.id NOT IN " +
|
|
"(SELECT DISTINCT tag_id FROM my_module_tags WHERE my_module_tags.my_module_id = #{id.to_s})"
|
|
)
|
|
end
|
|
|
|
def last_activities(count = Constants::ACTIVITY_AND_NOTIF_SEARCH_LIMIT)
|
|
Activity.where(my_module_id: id).order(:created_at).last(count)
|
|
end
|
|
|
|
# Get module comments ordered by created_at time. Results are paginated
|
|
# using last comment id and per_page parameters.
|
|
def last_comments(last_id = 1, per_page = Constants::COMMENTS_SEARCH_LIMIT)
|
|
last_id = Constants::INFINITY if last_id <= 1
|
|
comments = TaskComment.joins(:my_module)
|
|
.where(my_modules: { id: id })
|
|
.where('comments.id < ?', last_id)
|
|
.order(created_at: :desc)
|
|
.limit(per_page)
|
|
TaskComment.from(comments, :comments).order(created_at: :asc)
|
|
end
|
|
|
|
def last_activities(last_id = 1,
|
|
count = Constants::ACTIVITY_AND_NOTIF_SEARCH_LIMIT)
|
|
last_id = Constants::INFINITY if last_id <= 1
|
|
Activity.joins(:my_module)
|
|
.where(my_module_id: id)
|
|
.where('activities.id < ?', last_id)
|
|
.order(created_at: :desc)
|
|
.limit(count)
|
|
.uniq
|
|
end
|
|
|
|
def protocol
|
|
# Temporary function (until we fully support
|
|
# multiple protocols per module)
|
|
protocols.count > 0 ? protocols.first : nil
|
|
end
|
|
|
|
def is_overdue?(datetime = DateTime.current)
|
|
due_date.present? && datetime.utc > due_date.utc
|
|
end
|
|
|
|
def overdue_for_days(datetime = DateTime.current)
|
|
if due_date.blank? || due_date.utc > datetime.utc
|
|
0
|
|
else
|
|
((datetime.utc.to_i - due_date.utc.to_i) / 1.day.to_f).ceil
|
|
end
|
|
end
|
|
|
|
def is_one_day_prior?(datetime = DateTime.current)
|
|
is_due_in?(datetime, 1.day)
|
|
end
|
|
|
|
def is_due_in?(datetime, diff)
|
|
due_date.present? &&
|
|
datetime.utc < due_date.utc &&
|
|
datetime.utc > (due_date.utc - diff)
|
|
end
|
|
|
|
def space_taken
|
|
st = 0
|
|
protocol.steps.find_each do |step|
|
|
st += step.space_taken
|
|
end
|
|
results
|
|
.includes(:result_asset)
|
|
.find_each do |result|
|
|
st += result.space_taken
|
|
end
|
|
st
|
|
end
|
|
|
|
def archived_results
|
|
results
|
|
.select('results.*')
|
|
.select('ra.id AS result_asset_id')
|
|
.select('rt.id AS result_table_id')
|
|
.select('rx.id AS result_text_id')
|
|
.joins('LEFT JOIN result_assets AS ra ON ra.result_id = results.id')
|
|
.joins('LEFT JOIN result_tables AS rt ON rt.result_id = results.id')
|
|
.joins('LEFT JOIN result_texts AS rx ON rx.result_id = results.id')
|
|
.where(:archived => true)
|
|
end
|
|
|
|
# Treat this module as root, get all modules of that subtree
|
|
def downstream_modules
|
|
final = []
|
|
modules = [self]
|
|
until modules.blank?
|
|
my_module = modules.shift
|
|
final << my_module unless final.include?(my_module)
|
|
modules.push(*my_module.my_modules)
|
|
end
|
|
final
|
|
end
|
|
|
|
# Treat this module as inversed root, get all modules of that inversed subtree
|
|
def upstream_modules
|
|
final = []
|
|
modules = [self]
|
|
until modules.blank?
|
|
my_module = modules.shift
|
|
final << my_module unless final.include?(my_module)
|
|
modules.push(*my_module.my_module_antecessors)
|
|
end
|
|
final
|
|
end
|
|
|
|
# Generate the repository rows belonging to this module
|
|
# in JSON form, suitable for display in handsontable.js
|
|
def repository_json_hot(repository, order)
|
|
# Prepare column headers
|
|
headers = [
|
|
I18n.t('repositories.table.id'),
|
|
I18n.t('repositories.table.row_name'),
|
|
I18n.t('repositories.table.added_on'),
|
|
I18n.t('repositories.table.added_by')
|
|
]
|
|
data = []
|
|
rows = repository.assigned_rows(self).includes(:created_by).order(created_at: order)
|
|
if repository.has_stock_management?
|
|
headers.push(I18n.t('repositories.table.row_consumption'))
|
|
rows = rows.left_joins(my_module_repository_rows: :repository_stock_unit_item)
|
|
.select(
|
|
'repository_rows.*',
|
|
'my_module_repository_rows.stock_consumption'
|
|
)
|
|
end
|
|
rows.find_each do |row|
|
|
row_json = []
|
|
row_json << row.code
|
|
row_json << (row.archived ? "#{row.name} [#{I18n.t('general.archived')}]" : row.name)
|
|
row_json << I18n.l(row.created_at, format: :full)
|
|
row_json << row.created_by.full_name
|
|
if repository.has_stock_management?
|
|
if repository.is_a?(RepositorySnapshot)
|
|
consumed_stock = row.repository_stock_consumption_cell&.value&.formatted
|
|
row_json << (consumed_stock || 0)
|
|
else
|
|
consumed_stock_formatted =
|
|
if row.repository_stock_cell.present?
|
|
consumed_stock = number_with_precision(
|
|
row.stock_consumption || 0,
|
|
precision: (row.repository.repository_stock_column.metadata['decimals'].to_i || 0),
|
|
strip_insignificant_zeros: true
|
|
)
|
|
"#{consumed_stock} #{row.repository_stock_value&.repository_stock_unit_item&.data}"
|
|
else
|
|
'-'
|
|
end
|
|
row_json << consumed_stock_formatted
|
|
end
|
|
end
|
|
data << row_json
|
|
end
|
|
|
|
{ data: data, headers: headers }
|
|
end
|
|
|
|
def repository_docx_json(repository)
|
|
headers = [
|
|
I18n.t('repositories.table.id'),
|
|
I18n.t('repositories.table.row_name'),
|
|
I18n.t('repositories.table.added_on'),
|
|
I18n.t('repositories.table.added_by')
|
|
]
|
|
custom_columns = []
|
|
return false unless repository
|
|
|
|
repository.repository_columns.order(:id).each do |column|
|
|
if column.data_type == 'RepositoryStockValue'
|
|
headers.push(I18n.t('repositories.table.row_consumption'))
|
|
else
|
|
headers.push(column.name)
|
|
end
|
|
custom_columns.push(column.id)
|
|
end
|
|
|
|
records = repository.assigned_rows(self)
|
|
.select(:id, :name, :created_at, :created_by_id, :repository_id, :parent_id, :archived)
|
|
{ headers: headers, rows: records, custom_columns: custom_columns }
|
|
end
|
|
|
|
def deep_clone(current_user)
|
|
deep_clone_to_experiment(current_user, experiment)
|
|
end
|
|
|
|
def deep_clone_to_experiment(current_user, experiment_dest)
|
|
# Copy the module
|
|
clone = MyModule.new(
|
|
name: name,
|
|
experiment: experiment_dest,
|
|
description: description,
|
|
x: x,
|
|
y: y,
|
|
created_by: current_user
|
|
)
|
|
|
|
# set new position if cloning in the same experiment
|
|
clone.attributes = get_new_position if clone.experiment == experiment
|
|
|
|
clone.save!
|
|
|
|
clone.assign_user(current_user)
|
|
|
|
# Remove the automatically generated protocol,
|
|
# & clone the protocol instead
|
|
clone.protocol.destroy
|
|
clone.reload
|
|
|
|
# Update the cloned protocol if neccesary
|
|
clone_tinymce_assets(clone, clone.experiment.project.team)
|
|
clone.protocols << protocol.deep_clone_my_module(self, current_user)
|
|
clone.reload
|
|
|
|
# fixes linked protocols
|
|
clone.protocols.each do |protocol|
|
|
next unless protocol.linked?
|
|
|
|
protocol.updated_at = protocol.parent_updated_at
|
|
protocol.save
|
|
end
|
|
|
|
clone
|
|
end
|
|
|
|
# Find an empty position for the restored module. It's
|
|
# basically a first empty row with empty space inside x=[0, 32).
|
|
def get_new_position
|
|
return { x: 0, y: 0 } if experiment.blank?
|
|
|
|
# Get all modules position that overlap with first column, [0, WIDTH) and
|
|
# sort them by y coordinate.
|
|
positions = experiment.my_modules.active.collect { |m| [m.x, m.y] }
|
|
.select { |x, _| x >= 0 && x < WIDTH }
|
|
.sort_by { |_, y| y }
|
|
return { x: 0, y: 0 } if positions.blank? || positions.first[1] >= HEIGHT
|
|
|
|
# It looks we'll have to find a gap between the modules if it exists (at
|
|
# least 2*HEIGHT wide
|
|
ind = positions.each_cons(2).map { |f, s| s[1] - f[1] }
|
|
.index { |y| y >= 2 * HEIGHT }
|
|
return { x: 0, y: positions[ind][1] + HEIGHT } if ind
|
|
|
|
# We lucked out, no gaps, therefore we need to add it after the last element
|
|
{ x: 0, y: positions.last[1] + HEIGHT }
|
|
end
|
|
|
|
def assign_user(user, assigned_by = nil)
|
|
user_my_modules.create(
|
|
assigned_by: assigned_by || user,
|
|
user: user
|
|
)
|
|
Activities::CreateActivityService
|
|
.call(activity_type: :designate_user_to_my_module,
|
|
owner: assigned_by || user,
|
|
team: experiment.project.team,
|
|
project: experiment.project,
|
|
subject: self,
|
|
message_items: { my_module: id,
|
|
user_target: user.id })
|
|
end
|
|
|
|
def comments
|
|
task_comments
|
|
end
|
|
|
|
def permission_parent
|
|
experiment
|
|
end
|
|
|
|
private
|
|
|
|
def create_blank_protocol
|
|
protocols << Protocol.new_blank_for_module(self)
|
|
end
|
|
|
|
def coordinates_uniqueness_check
|
|
if experiment && experiment.my_modules.active.where(x: x, y: y).where.not(id: id).any?
|
|
errors.add(:position, I18n.t('activerecord.errors.models.my_module.attributes.position.not_unique'))
|
|
end
|
|
end
|
|
|
|
def assign_default_status_flow
|
|
return if my_module_status.present? || MyModuleStatusFlow.global.blank?
|
|
|
|
self.my_module_status = MyModuleStatusFlow.global.last.initial_status
|
|
end
|
|
|
|
def check_status_conditions
|
|
return if my_module_status.blank?
|
|
|
|
my_module_status.my_module_status_conditions.each do |condition|
|
|
condition.call(self)
|
|
end
|
|
end
|
|
|
|
def check_status_implications
|
|
return if my_module_status.blank?
|
|
|
|
my_module_status.my_module_status_implications.each do |implication|
|
|
implication.call(self)
|
|
end
|
|
end
|
|
|
|
def check_status
|
|
return unless my_module_status_id_was
|
|
|
|
original_status = MyModuleStatus.find_by(id: my_module_status_id_was)
|
|
unless my_module_status && [original_status.next_status, original_status.previous_status].include?(my_module_status)
|
|
errors.add(:my_module_status_id,
|
|
I18n.t('activerecord.errors.models.my_module.attributes.my_module_status_id.not_correct_order'))
|
|
end
|
|
end
|
|
|
|
def exec_status_consequences
|
|
return if my_module_status.blank? || status_changing
|
|
|
|
self.changing_from_my_module_status_id = my_module_status_id_was if my_module_status_id_was.present?
|
|
self.status_changing = true
|
|
|
|
status_changing_direction = my_module_status.previous_status_id == my_module_status_id_was ? :forward : :backward
|
|
|
|
yield
|
|
|
|
if my_module_status.my_module_status_consequences.any?(&:runs_in_background?)
|
|
MyModuleStatusConsequencesJob
|
|
.perform_later(self, my_module_status.my_module_status_consequences.to_a, status_changing_direction)
|
|
else
|
|
MyModuleStatusConsequencesJob
|
|
.perform_now(self, my_module_status.my_module_status_consequences.to_a, status_changing_direction)
|
|
end
|
|
end
|
|
|
|
def archiving_and_restoring_extras
|
|
if archived?
|
|
# Removes connections with other modules
|
|
self.x = 0
|
|
self.y = 0
|
|
# Remove association with module group.
|
|
self.my_module_group = nil
|
|
# Remove all connection between modules.
|
|
Connection.where(input_id: id).destroy_all
|
|
Connection.where(output_id: id).destroy_all
|
|
else
|
|
# Calculate new module position
|
|
new_pos = get_new_position
|
|
self.x = new_pos[:x]
|
|
self.y = new_pos[:y]
|
|
end
|
|
end
|
|
end
|