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:
parent
4ca7c25480
commit
678b5ada31
9 changed files with 139 additions and 34 deletions
|
@ -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:
|
||||||
|
|
|
@ -932,12 +932,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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -1125,7 +1125,7 @@ test("object manager form 1", function() {
|
||||||
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
|
||||||
},
|
},
|
||||||
|
|
|
@ -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
|
|
@ -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' => '',
|
||||||
}
|
}
|
||||||
|
@ -56,10 +58,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,
|
||||||
}
|
}
|
||||||
|
@ -67,10 +71,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',
|
||||||
|
@ -80,34 +86,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',
|
||||||
|
@ -124,6 +136,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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue