Fixes #3810 - Custom date and datetime attributes are filled with dates on creation of tickets/users after update from 4.1 to 5.x.

This commit is contained in:
Mantas Masalskis 2021-10-20 18:54:33 +02:00 committed by Rolf Schmidt
parent de9bb8bda9
commit 501a98b6c2
9 changed files with 139 additions and 34 deletions

View file

@ -244,7 +244,7 @@ class App.UiElement.object_manager_attribute extends App.UiElement.ApplicationUi
params: params params: params
) )
configureAttributes = [ configureAttributes = [
{ name: 'data_option::diff', display: 'Default time Diff (minutes)', tag: 'integer', null: false, default: 24 }, { name: 'data_option::diff', display: 'Default time Diff (minutes)', tag: 'integer', null: true },
] ]
datetimeDiff = new App.ControllerForm( datetimeDiff = new App.ControllerForm(
model: model:
@ -258,7 +258,7 @@ class App.UiElement.object_manager_attribute extends App.UiElement.ApplicationUi
@date: (item, localParams, params) -> @date: (item, localParams, params) ->
configureAttributes = [ configureAttributes = [
{ name: 'data_option::diff', display: 'Default time Diff (hours)', tag: 'integer', null: false, default: 24 }, { name: 'data_option::diff', display: 'Default time Diff (hours)', tag: 'integer', null: true },
] ]
dateDiff = new App.ControllerForm( dateDiff = new App.ControllerForm(
model: model:

View file

@ -946,12 +946,7 @@ is certain attribute used by triggers, overviews or schedulers
[{ failed: local_data_option[:future].nil?, [{ failed: local_data_option[:future].nil?,
message: 'must have boolean value for :future' }, message: 'must have boolean value for :future' },
{ failed: local_data_option[:past].nil?, { failed: local_data_option[:past].nil?,
message: 'must have boolean value for :past' }, message: 'must have boolean value for :past' }]
{ failed: local_data_option[:diff].nil?,
message: 'must have integer value for :diff (in hours)' }]
when 'date'
[{ failed: local_data_option[:diff].nil?,
message: 'must have integer value for :diff (in days)' }]
else else
[] []
end end

View file

@ -15,25 +15,30 @@ class ObjectManager
method_name = "#{attr}=" method_name = "#{attr}="
return if !record.respond_to? method_name return if !record.respond_to? method_name
return if record.send(attr).present? return if record.send("#{attr}_came_from_user?")
record.send method_name, build_value(config) record.send method_name, build_value(config)
end end
def build_value(config) def build_value(config)
case config[:data_type] method_name = "build_value_#{config[:data_type]}"
when 'date'
config[:diff].days.from_now return send(method_name, config) if respond_to?(method_name, true)
when 'datetime'
config[:diff].hours.from_now config[:default]
else end
config[:default]
end def build_value_date(config)
config[:diff]&.days&.from_now
end
def build_value_datetime(config)
config[:diff]&.hours&.from_now&.change(usec: 0, sec: 0)
end end
def attributes_for(record) def attributes_for(record)
query = ObjectManager::Attribute.active.editable.for_object(record.class) query = ObjectManager::Attribute.active.editable.for_object(record.class)
cache_key = "#{query.cache_key}/attribute_defaults" cache_key = "#{query.cache_key_with_version}/attribute_defaults"
Rails.cache.fetch cache_key do Rails.cache.fetch cache_key do
query query

View file

@ -0,0 +1,18 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
class Issue3810CustomDateAttributeNoDefault < ActiveRecord::Migration[6.0]
def up
return if !Setting.exists?(name: 'system_init_done')
ObjectManager::Attribute
.where(data_type: %i[date datetime])
.each { |elem| update_single(elem) }
end
def update_single(elem)
elem.data_option[:diff] = nil
elem.save!
rescue => e
Rails.logger.error e
end
end

View file

@ -1125,7 +1125,7 @@ QUnit.test("object manager form 1", assert => {
params = App.ControllerForm.params(el) params = App.ControllerForm.params(el)
var test_params = { var test_params = {
data_option: { data_option: {
diff: 24, diff: null,
future: true, future: true,
past: true past: true
}, },

View file

@ -0,0 +1,21 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'rails_helper'
RSpec.describe Issue3810CustomDateAttributeNoDefault, type: :db_migration, db_strategy: :reset_all do
before :all do # rubocop:disable RSpec/BeforeAfterAll
create('object_manager_attribute_date', name: 'rspec_date', default: 24)
create('object_manager_attribute_datetime', name: 'rspec_datetime', default: 24)
ObjectManager::Attribute.migration_execute
end
after :all do # rubocop:disable RSpec/BeforeAfterAll
ObjectManager::Attribute.where('name LIKE ?', 'rspec_%').destroy_all
end
it 'unsets diff migration' do
migrate
expect(create(:ticket)).to have_attributes(rspec_date: nil, rspec_datetime: nil)
end
end

View file

@ -41,6 +41,8 @@ FactoryBot.define do
end end
factory :object_manager_attribute_text, parent: :object_manager_attribute do factory :object_manager_attribute_text, parent: :object_manager_attribute do
default { '' }
data_type { 'input' } data_type { 'input' }
data_option do data_option do
{ {
@ -48,7 +50,7 @@ FactoryBot.define do
'maxlength' => 200, 'maxlength' => 200,
'null' => true, 'null' => true,
'translate' => false, 'translate' => false,
'default' => default || '', 'default' => default,
'options' => {}, 'options' => {},
'relation' => '', 'relation' => '',
} }
@ -71,10 +73,12 @@ FactoryBot.define do
end end
factory :object_manager_attribute_integer, parent: :object_manager_attribute do factory :object_manager_attribute_integer, parent: :object_manager_attribute do
default { 0 }
data_type { 'integer' } data_type { 'integer' }
data_option do data_option do
{ {
'default' => default || 0, 'default' => default,
'min' => 0, 'min' => 0,
'max' => 9999, 'max' => 9999,
} }
@ -82,10 +86,12 @@ FactoryBot.define do
end end
factory :object_manager_attribute_boolean, parent: :object_manager_attribute do factory :object_manager_attribute_boolean, parent: :object_manager_attribute do
default { false }
data_type { 'boolean' } data_type { 'boolean' }
data_option do data_option do
{ {
default: default || false, default: default,
options: { options: {
true => 'yes', true => 'yes',
false => 'no', false => 'no',
@ -95,34 +101,40 @@ FactoryBot.define do
end end
factory :object_manager_attribute_date, parent: :object_manager_attribute do factory :object_manager_attribute_date, parent: :object_manager_attribute do
default { 24 }
name { 'date_attribute' } name { 'date_attribute' }
data_type { 'date' } data_type { 'date' }
data_option do data_option do
{ {
'diff' => default || 24, 'diff' => default,
'null' => true, 'null' => true,
} }
end end
end end
factory :object_manager_attribute_datetime, parent: :object_manager_attribute do factory :object_manager_attribute_datetime, parent: :object_manager_attribute do
default { 24 }
name { 'datetime_attribute' } name { 'datetime_attribute' }
data_type { 'datetime' } data_type { 'datetime' }
data_option do data_option do
{ {
'future' => true, 'future' => true,
'past' => true, 'past' => true,
'diff' => default || 24, 'diff' => default,
'null' => true, 'null' => true,
} }
end end
end end
factory :object_manager_attribute_select, parent: :object_manager_attribute do factory :object_manager_attribute_select, parent: :object_manager_attribute do
default { '' }
data_type { 'select' } data_type { 'select' }
data_option do data_option do
{ {
'default' => default || '', 'default' => default,
'options' => { 'options' => {
'key_1' => 'value_1', 'key_1' => 'value_1',
'key_2' => 'value_2', 'key_2' => 'value_2',
@ -139,6 +151,8 @@ FactoryBot.define do
end end
factory :object_manager_attribute_tree_select, parent: :object_manager_attribute do factory :object_manager_attribute_tree_select, parent: :object_manager_attribute do
default { '' }
data_type { 'tree_select' } data_type { 'tree_select' }
data_option do data_option do
{ {

View file

@ -2,18 +2,21 @@
require 'rails_helper' require 'rails_helper'
DEFAULT_VALUES = {
text: 'rspec',
boolean: true,
date: 1,
datetime: 12,
integer: 123,
select: 'key_1'
}.freeze
RSpec.describe ObjectManager::Attribute::SetDefaults, type: :model do RSpec.describe ObjectManager::Attribute::SetDefaults, type: :model do
describe 'setting default', db_strategy: :reset_all do describe 'setting default', db_strategy: :reset_all do
before :all do # rubocop:disable RSpec/BeforeAfterAll before :all do # rubocop:disable RSpec/BeforeAfterAll
{ DEFAULT_VALUES.each do |key, value|
text: 'rspec',
boolean: true,
date: 1,
datetime: 12,
integer: 123,
select: 'key_1'
}.each do |key, value|
create("object_manager_attribute_#{key}", name: "rspec_#{key}", default: value) create("object_manager_attribute_#{key}", name: "rspec_#{key}", default: value)
create("object_manager_attribute_#{key}", name: "rspec_#{key}_no_default", default: nil)
end end
create('object_manager_attribute_text', name: 'rspec_empty', default: '') create('object_manager_attribute_text', name: 'rspec_empty', default: '')
@ -77,7 +80,7 @@ RSpec.describe ObjectManager::Attribute::SetDefaults, type: :model do
end end
it 'datetime is set' do it 'datetime is set' do
freeze_time travel_to Time.current.change(usec: 0, sec: 0)
expect(example.rspec_datetime).to eq 12.hours.from_now expect(example.rspec_datetime).to eq 12.hours.from_now
end end
@ -89,5 +92,28 @@ RSpec.describe ObjectManager::Attribute::SetDefaults, type: :model do
expect(example.rspec_select).to eq 'key_1' expect(example.rspec_select).to eq 'key_1'
end end
end end
context 'when overriding default to empty value' do
subject(:example) do
params = DEFAULT_VALUES.keys.each_with_object({}) { |elem, memo| memo["rspec_#{elem}"] = nil }
create :ticket, params
end
DEFAULT_VALUES.each_key do |elem|
it "#{elem} is empty" do
expect(example.send("rspec_#{elem}")).to be_nil
end
end
end
context 'when default is not set' do
subject(:example) { create :ticket }
DEFAULT_VALUES.each_key do |elem|
it "#{elem} is empty" do
expect(example.send("rspec_#{elem}_no_default")).to be_nil
end
end
end
end end
end end

View file

@ -489,4 +489,30 @@ RSpec.describe 'System > Objects', type: :system do
end end
end end
end end
context 'when creating with no diff' do
before do
visit '/#system/object_manager'
page.find('.js-new').click
in_modal disappears: false do
fill_in 'Name', with: 'nodiff'
fill_in 'Display', with: 'NoDiff'
end
end
it 'date attribute' do
page.find('select[name=data_type]').select('Date')
fill_in 'Default time Diff (hours)', with: ''
expect { page.find('.js-submit').click }.to change(ObjectManager::Attribute, :count).by(1)
end
it 'datetime attribute' do
page.find('select[name=data_type]').select('Datetime')
fill_in 'Default time Diff (minutes)', with: ''
expect { page.find('.js-submit').click }.to change(ObjectManager::Attribute, :count).by(1)
end
end
end end