added :schedule_manually attribute to work package

pull/8342/head
Markus Kahl 5 years ago
parent ebdd8e0d8a
commit 9c4d4ebc46
  1. 2
      app/contracts/work_packages/base_contract.rb
  2. 4
      app/models/work_package/scheduling_rules.rb
  3. 1
      config/locales/en.yml
  4. 9
      db/migrate/20200504085933_add_schedule_manually_to_work_packages.rb
  5. 3
      docs/api/apiv3/endpoints/work-packages.apib
  6. 5
      lib/api/v3/work_packages/schema/work_package_schema_representer.rb
  7. 8
      lib/api/v3/work_packages/work_package_representer.rb
  8. 11
      spec/lib/api/v3/work_packages/schema/work_package_schema_representer_spec.rb
  9. 22
      spec/lib/api/v3/work_packages/work_package_payload_representer_spec.rb
  10. 26
      spec/lib/api/v3/work_packages/work_package_representer_spec.rb
  11. 40
      spec/requests/api/v3/work_package_resource_spec.rb

@ -80,6 +80,8 @@ module WorkPackages
model.project.possible_responsible_members
end
attribute :schedule_manually
attribute :start_date,
writeable: ->(*) {
model.leaf?

@ -38,6 +38,10 @@ module WorkPackage::SchedulingRules
.call(date)
end
def schedule_automatically?
!schedule_manually?
end
# Calculates the minimum date that
# will not violate the precedes relations (max(finish date, start date) + delay)
# of this work package or its ancestors

@ -535,6 +535,7 @@ en:
parent_work_package: "Parent"
priority: "Priority"
progress: "Progress (%)"
schedule_manually: "Schedule manually"
spent_hours: "Spent time"
spent_time: "Spent time"
subproject: "Subproject"

@ -0,0 +1,9 @@
class AddScheduleManuallyToWorkPackages < ActiveRecord::Migration[6.0]
def change
add_column :work_packages, :schedule_manually, :boolean, default: false
# We add a partial index here because 90% of the values will be false.
# So we only index the true values. This way the index is actually useful.
add_index :work_packages, :schedule_manually, where: :schedule_manually
end
end

@ -50,6 +50,7 @@
| subject | Work package subject | String | not null; 1 <= length <= 255 | READ / WRITE | |
| type | Name of the work package's type | String | not null | READ | |
| description | The work package description | Formattable | | READ / WRITE | |
| scheduleManually | If false (default) schedule automatically. | Boolean | | READ / WRITE | |
| startDate | Scheduled beginning of a work package | Date | Cannot be set for parent work packages; must be equal or greater than the earliest possible start date; Exists only on work packages of a non milestone type | READ / WRITE | |
| dueDate | Scheduled end of a work package | Date | Cannot be set for parent work packages; must be greater than or equal to the start date; Exists only on work packages of a non milestone type | READ / WRITE | |
| date | Date on which a milestone is achieved | Date | Exists only on work packages of a milestone type
@ -257,6 +258,7 @@ and [update](#work-packages-work-package-patch). The attachments the work packag
"raw": "Develop super cool OpenProject API.",
"html": "<p>Develop super cool OpenProject API.</p>"
},
"scheduleManually": false,
"startDate": null,
"dueDate": null,
"estimatedTime": "PT2H",
@ -2312,4 +2314,3 @@ Gets a list of users that can be assigned as the responsible of a work package i
"errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound",
"message": "The specified project does not exist."
}

@ -119,6 +119,11 @@ module API
type: 'Formattable',
required: false
schema :schedule_manually,
type: 'Boolean',
required: false,
has_default: true
schema :start_date,
type: 'Date',
required: false,

@ -329,6 +329,10 @@ module API
formattable_property :description
property :schedule_manually,
exec_context: :decorator,
getter: ->(*) { represented.schedule_manually? }
date_property :start_date,
skip_render: ->(represented:, **) {
represented.milestone?
@ -544,6 +548,10 @@ module API
@visible_children ||= represented.children.select(&:visible?)
end
def schedule_manually=(value)
represented.schedule_manually = value
end
def estimated_time=(value)
represented.estimated_hours = datetime_formatter.parse_duration_to_hours(value,
'estimatedTime',

@ -289,6 +289,17 @@ describe ::API::V3::WorkPackages::Schema::WorkPackageSchemaRepresenter do
end
end
describe 'scheduleManually' do
it_behaves_like 'has basic schema properties' do
let(:path) { 'scheduleManually' }
let(:type) { 'Boolean' }
let(:name) { I18n.t('activerecord.attributes.work_package.schedule_manually') }
let(:required) { false }
let(:has_default) { true }
let(:writable) { true }
end
end
describe 'date' do
before do
allow(schema)

@ -485,6 +485,28 @@ describe ::API::V3::WorkPackages::WorkPackagePayloadRepresenter do
end
end
describe 'scheduleManually' do
let(:value) { raise "define value" }
let(:attributes) { { scheduleManually: value } }
context 'with true' do
let(:value) { true }
it 'reads true' do
expect(subject.schedule_manually).to eq true
end
end
context 'with false' do
let(:value) { false }
it 'reads false' do
expect(subject.schedule_manually).to eq false
end
end
end
describe 'startDate' do
it_behaves_like 'settable ISO 8601 date only' do
let(:property) { :startDate }

@ -41,6 +41,7 @@ describe ::API::V3::WorkPackages::WorkPackageRepresenter do
let(:priority) { FactoryBot.build_stubbed(:priority, updated_at: Time.now) }
let(:assignee) { nil }
let(:responsible) { nil }
let(:schedule_manually) { nil }
let(:start_date) { Date.today.to_datetime }
let(:due_date) { Date.today.to_datetime }
let(:type_milestone) { false }
@ -49,6 +50,7 @@ describe ::API::V3::WorkPackages::WorkPackageRepresenter do
let(:spent_hours) { 0 }
let(:work_package) do
FactoryBot.build_stubbed(:stubbed_work_package,
schedule_manually: schedule_manually,
start_date: start_date,
due_date: due_date,
done_ratio: 50,
@ -122,6 +124,30 @@ describe ::API::V3::WorkPackages::WorkPackageRepresenter do
let(:html) { '<p>' + work_package.description + '</p>' }
end
describe 'scheduleManually' do
context 'no value' do
it 'renders as false (default value)' do
is_expected.to be_json_eql(false.to_json).at_path('scheduleManually')
end
end
context 'false' do
let(:schedule_manually) { false }
it 'renders as false' do
is_expected.to be_json_eql(false.to_json).at_path('scheduleManually')
end
end
context 'true' do
let(:schedule_manually) { true }
it 'renders as true' do
is_expected.to be_json_eql(true.to_json).at_path('scheduleManually')
end
end
end
describe 'startDate' do
it_behaves_like 'has ISO 8601 date only' do
let(:date) { start_date }

@ -474,6 +474,19 @@ describe 'API v3 Work package resource',
end
end
context 'schedule manually' do
let(:schedule_manually) { true }
let(:params) { valid_params.merge(scheduleManually: schedule_manually) }
include_context 'patch request'
it { expect(response.status).to eq(200) }
it 'should update the scheduling mode' do
expect(subject.body).to be_json_eql(schedule_manually.to_json).at_path('scheduleManually')
end
end
context 'start date' do
let(:dateString) { Date.today.to_date.iso8601 }
let(:params) { valid_params.merge(startDate: dateString) }
@ -1260,6 +1273,33 @@ describe 'API v3 Work package resource',
end
end
context 'schedule manually' do
let(:work_package) { WorkPackage.first }
context 'with true' do
# mind the () for the super call, those are required in rspec's super
let(:parameters) { super().merge(scheduleManually: true) }
it 'should set the scheduling mode to true' do
expect(work_package.schedule_manually).to eq true
end
end
context 'with false' do
let(:parameters) { super().merge(scheduleManually: false) }
it 'should set the scheduling mode to false' do
expect(work_package.schedule_manually).to eq false
end
end
context 'with scheduleManually absent' do
it 'should set the scheduling mode to false (default)' do
expect(work_package.schedule_manually).to eq false
end
end
end
context 'invalid value' do
let(:parameters) do
{

Loading…
Cancel
Save