# Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ module Import module OTRS class Article include Import::Helper include Import::OTRS::Helper MAPPING = { TicketID: :ticket_id, ArticleID: :id, Body: :body, From: :from, To: :to, Cc: :cc, Subject: :subject, InReplyTo: :in_reply_to, MessageID: :message_id, # ReplyTo: :reply_to, References: :references, ContentType: :content_type, ChangeTime: :updated_at, CreateTime: :created_at, ChangeBy: :updated_by_id, CreateBy: :created_by_id, # Support also the legacy key names (lower then OTRS 6) Changed: :updated_at, Created: :created_at, ChangedBy: :updated_by_id, CreatedBy: :created_by_id, }.freeze def initialize(article) initialize_article_sender_types initialize_article_types utf8_encode(article) import(article) end private def import(article) create_or_update(map(article)) return if article['Attachments'].blank? Import::OTRS::Article::AttachmentFactory.import( attachments: article['Attachments'], local_article: @local_article ) end def create_or_update(article) return if updated?(article) create(article) end def updated?(article) @local_article = ::Ticket::Article.find_by(id: article[:id]) return false if !@local_article log "update Ticket::Article.find_by(id: #{article[:id]})" @local_article.update!(article) true end def create(article) log "add Ticket::Article.find_by(id: #{article[:id]})" @local_article = ::Ticket::Article.new(article) @local_article.id = article[:id] @local_article.save reset_primary_key_sequence('ticket_articles') rescue ActiveRecord::RecordNotUnique log "Ticket #{article[:ticket_id]} (article #{article[:id]}) is handled by another thead, skipping." end def map(article) mapped = map_default(article) map_content_type(mapped) mapped[:body] ||= '' mapped end def map_default(article) { created_by_id: 1, updated_by_id: 1, } .merge(from_mapping(article)) .merge(article_type(article)) .merge(article_sender_type(article)) .merge(article_created_and_updated_by_id(article)) end def map_content_type(mapped) # if no content type is set make sure to remove it # so Zammad can set the default content type mapped.delete(:content_type) if mapped[:content_type].blank? return mapped if !mapped[:content_type] mapped[:content_type].sub!(%r{[;,]\s?.+?$}, '') mapped end def article_type(article) @article_types[article['ArticleType']] || @article_types['note-internal'] end def article_sender_type(article) { sender_id: @sender_type_id[article['SenderType']] || @sender_type_id['note-internal'] } end def article_created_and_updated_by_id(article) return {} if article['SenderType'] != 'customer' created_by_id = get_article_created_by_id(article) return {} if get_article_created_by_id(article) != 1 return {} if article['From'].blank? user = Import::OTRS::ArticleCustomer.find(article) return {} if !user mapping = { created_by_id: user.id, } updated_by_id = get_article_updated_by_id(article) if !updated_by_id || updated_by_id == created_by_id mapping[:updated_by_id] = user.id end mapping end def get_article_created_by_id(article) return article['CreatedBy'].to_i if article['CreatedBy'].present? article['CreateBy'].to_i end def get_article_updated_by_id(article) return article['UpdatedBy'].to_i if article['UpdatedBy'].present? return article['UpdateBy'].to_i if article['UpdateBy'].present? nil end def initialize_article_sender_types @sender_type_id = { 'customer' => article_sender_type_id_lookup('Customer'), 'agent' => article_sender_type_id_lookup('Agent'), 'system' => article_sender_type_id_lookup('System'), } end def article_sender_type_id_lookup(name) ::Ticket::Article::Sender.find_by(name: name).id end def initialize_article_types @article_types = { 'email-external' => { type_id: article_type_id_lookup('email'), internal: false }, 'email-internal' => { type_id: article_type_id_lookup('email'), internal: true }, 'note-external' => { type_id: article_type_id_lookup('note'), internal: false }, 'note-internal' => { type_id: article_type_id_lookup('note'), internal: true }, 'phone' => { type_id: article_type_id_lookup('phone'), internal: false }, 'webrequest' => { type_id: article_type_id_lookup('web'), internal: false }, } end def article_type_id_lookup(name) ::Ticket::Article::Type.lookup(name: name).id end end end end