Initial Redmine tooling and local plugin forks

This commit is contained in:
Jason Thistlethwaite
2026-04-24 22:01:18 +00:00
commit 9f682af0eb
683 changed files with 56878 additions and 0 deletions
@@ -0,0 +1,121 @@
# This file is a part of Redmine CRM (redmine_contacts) plugin,
# customer relationship management plugin for Redmine
#
# Copyright (C) 2010-2018 RedmineUP
# http://www.redmineup.com/
#
# redmine_contacts 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, either version 3 of the License, or
# (at your option) any later version.
#
# redmine_contacts 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 redmine_contacts. If not, see <http://www.gnu.org/licenses/>.
module CSVImportable
class << self; attr_accessor :klass end
def persisted?
false
end
def initialize(attributes = {})
attributes.each{|name, value| send("#{name}=", value)}
end
def save
if imported_instances.any? && imported_instances.map(&:valid?).all? && imported_instances.map{|c| c.new_record? ? true : (c.respond_to?('editable?') ? c.editable? : true)}.all?
begin
klass.transaction do
imported_instances.each(&:save!)
end
rescue
Rails.logger.info $!.message
Rails.logger.info $!.backtrace.join("\n")
return false
end
true
else
imported_instances.each_with_index do |instance, index|
if !instance.new_record? && !instance.editable?
errors.add :base, "Row #{index + 2}: Permission restricted for changing #{klass.name}"
else
instance.errors.full_messages.each do |message|
errors.add :base, "Row #{index + 2}: #{message}"
end
end
end
false
end
end
def imported_instances
@imported_instances ||= load_imported_instances
end
protected
def force_utf8(v)
if v.respond_to? :force_encoding then v.force_encoding('utf-8') else v end
end
private
def build_custom_fields
custom_fields_attributes = {}
klass.new.custom_field_values.each do |custom_field_value|
custom_fields_attributes[custom_field_value.custom_field.id.to_s] = custom_field_value.custom_field.cast_value(row[custom_field_value.custom_field.name]).to_s
end
custom_fields_attributes
end
def load_imported_instances
instance_rows = open_import_source
klass.transaction do
begin
line_counter = 0
instance_rows.map do |row|
line_counter += 1
instance = klass.find_by_id(row['#']) || klass.new
instance.attributes = build_from_fcsv_row(row)
if instance.respond_to?(:custom_field_values)
instance.custom_field_values.each do |custom_field_value|
custom_field_value.value = custom_field_value.custom_field.cast_value(row[custom_field_value.custom_field.name.underscore]).to_s
end
end
instance.project = project if instance.respond_to?(:project=)
puts instance.errors.full_messages unless instance.valid?
instance
end
rescue
Rails.logger.info $!.message
Rails.logger.info $!.backtrace.join("\n")
errors.add :base, I18n.t(:text_crm_error_on_line, :line => line_counter, :error => $!.message)
[]
end
end
end
def open_import_source
begin
content = file.read
FCSV.parse(content, :headers => true, :header_converters => [:downcase], :encoding => 'utf-8', :col_sep => guess_separator(force_utf8(content)), :quote_char => quotes_type)
rescue Exception => e
Rails.logger.info $!.message
Rails.logger.info $!.backtrace.join("\n")
errors.add :base, e.message
[]
end
end
def guess_separator(content)
first_line = content.split("\n").first
commas = first_line.count(",")
semicolons = first_line.count(";")
commas > semicolons ? ',' : ';'
end
end