123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- class Checklist::Item < ApplicationModel
- include ChecksClientNotification
- include HasHistory
- include HasDefaultModelUserRelations
- include Checklist::Item::Assets
- include Checklist::Item::TriggersSubscriptions
- attr_accessor :initial_clone
- belongs_to :checklist
- belongs_to :ticket, optional: true, inverse_of: :referencing_checklist_items
- scope :incomplete, -> { where(checked: false) }
- before_validation :detect_ticket_reference, unless: :initial_clone
- before_validation :detect_ticket_reference_state
- validate :detect_ticket_loop_reference, unless: -> { ticket.blank? }
- validate :validate_item_count, on: :create, unless: :initial_clone
- # MySQL does not support default value on non-null text columns
- # Can be removed after dropping MySQL
- before_validation :ensure_text_not_nil, if: -> { ActiveRecord::Base.connection_db_config.configuration_hash[:adapter] == 'mysql2' }
- after_update :history_update_checked, if: -> { saved_change_to_checked? }
- after_destroy :update_checklist_on_destroy
- after_destroy :update_referenced_ticket
- after_save :update_checklist_on_save, unless: :initial_clone
- after_save :update_referenced_ticket
- history_attributes_ignored :checked
- def history_log_attributes
- {
- related_o_id: checklist.ticket.id,
- related_history_object: 'Ticket',
- }
- end
- def history_create
- history_log('created', created_by_id, { value_to: text })
- end
- def history_update_checked
- history_log('checklist_item_checked', updated_by_id, {
- value_from: text,
- value_to: checked.to_s,
- })
- end
- def history_destroy
- history_log('removed', updated_by_id, { value_to: text })
- end
- def notify_clients_data_attributes
- {
- id: id,
- updated_at: updated_at,
- updated_by_id: updated_by_id,
- }
- end
- private
- def update_checklist_on_save
- checklist.sorted_item_ids |= [id.to_s]
- # It is necessary to make checklist dirty if checklist item was edited, but sorting was not changed
- # Otherwise legacy UI will not update properly
- checklist.updated_at = Time.current
- checklist.save!
- end
- def update_checklist_on_destroy
- # do not touch checklist if this item is destroyed by checklist's dependent: destroy
- return if destroyed_by_association
- checklist.sorted_item_ids -= [id.to_s]
- checklist.save!
- end
- def detect_ticket_reference
- return if ticket_id_changed?
- ticket = Ticket::Number.check(text)
- return if ticket.blank?
- self.ticket = ticket
- end
- def detect_ticket_reference_state
- return if !ticket
- return if !ticket_id_changed?
- self.checked = Checklist.ticket_closed?(ticket)
- end
- def detect_ticket_loop_reference
- return if checklist_id != ticket.checklist_id
- errors.add(:ticket, __('reference must not be the checklist ticket.'))
- end
- def validate_item_count
- return if checklist.items.count < 100
- errors.add(:base, __('Checklist items are limited to 100 items per checklist.'))
- end
- def update_referenced_ticket
- return if !saved_change_to_ticket_id? && !destroyed?
- [ticket_id, ticket_id_before_last_save]
- .compact
- .map { |elem| Ticket.find_by(id: elem) }
- .each do |elem|
- elem.updated_at = Time.current
- elem.save!
- end
- end
- # MySQL does not support default value on non-null text columns
- # Can be removed after dropping MySQL
- def ensure_text_not_nil
- self.text ||= ''
- end
- end
|