1/* This file is part of the KDE project
2 Copyright (C) 2001 Thomas Zander zander@kde.org
3 Copyright (C) 2004-2007 Dag Andersen <danders@get2net.dk>
4 Copyright (C) 2011 Dag Andersen <danders@get2net.dk>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19* Boston, MA 02110-1301, USA.
20*/
21
22#ifndef KPTRESOURCE_H
23#define KPTRESOURCE_H
24
25#include "kplatokernel_export.h"
26
27#include "kptglobal.h"
28#include "kptduration.h"
29#include "kptdatetime.h"
30#include "kptappointment.h"
31#include "kptcalendar.h"
32
33#include <QDomDocument>
34#include <QHash>
35#include <QString>
36#include <QList>
37
38#include <kdebug.h>
39
40#include <KoXmlReader.h>
41
42class QTime;
43
44
45/// The main namespace.
46namespace KPlato
47{
48
49class Account;
50class Risk;
51class Effort;
52class Appointment;
53class Task;
54class Node;
55class Project;
56class Resource;
57class ResourceRequest;
58class ResourceGroupRequest;
59class ResourceRequestCollection;
60class Schedule;
61class NodeSchedule;
62class ResourceSchedule;
63class Schedule;
64class XMLLoaderObject;
65class DateTimeInterval;
66
67/**
68 * This class represents a group of similar resources to be assigned to a task
69 * e.g. The list of employees, computer resources, etc
70 */
71
72/* IDEA; lets create a resourceGroup that has the intelligence to import PIM schedules
73 * from the kroupware project and use the schedules to use the factory pattern to build
74 * Resources (probably a derived class) which returns values on getFirstAvailableTime
75 * and friends based on the schedules we got from the PIM projects.
76 * (Thomas Zander mrt-2003 by suggestion of Shaheed)
77 */
78
79class KPLATOKERNEL_EXPORT ResourceGroup : public QObject
80{
81 Q_OBJECT
82public:
83 /// Default constructor
84 explicit ResourceGroup();
85 explicit ResourceGroup( const ResourceGroup *group );
86 ~ResourceGroup();
87
88 enum Type { Type_Work, Type_Material };
89
90 QString id() const { return m_id; }
91 void setId( const QString& id );
92
93 Project *project() { return m_project; }
94
95 void setName( const QString& n );
96 const QString &name() const { return m_name;}
97 void setType( Type type );
98 void setType(const QString &type);
99 Type type() const { return m_type; }
100 QString typeToString( bool trans = false ) const;
101 static QStringList typeToStringList( bool trans = false );
102
103 bool isScheduled() const;
104
105 /// Return true if any resource in this group is baselined
106 bool isBaselined( long id = BASELINESCHEDULE ) const;
107
108 /** Manage the resources in this list
109 * <p>At some point we will have to look at not mixing types of resources
110 * (e.g. you can't add a person to a list of computers
111 *
112 * <p>Risks must always be associated with a resource, so there is no option
113 * to manipulate risks (@ref Risk) separately
114 */
115 void addResource( int index, Resource*, Risk* );
116 Resource *takeResource( Resource *resource );
117 QList<Resource*> resources() const { return m_resources; }
118 int indexOf( const Resource *resource ) const;
119 Resource *resourceAt( int pos ) const { return m_resources.value( pos ); }
120 int numResources() const { return m_resources.count(); }
121
122 Risk* getRisk( int );
123
124 /** Get the "num" resources which is available in the time frame
125 * defined by "start" and "duration".
126 * @param start todo
127 * @param duration todo
128 * @param num todo
129 */
130 QList<Resource> availableResources( const DateTime start, const Duration duration, int num );
131 /** Manage the dependent resources. This is a list of the resource
132 * groups that must have available resources for this resource to
133 * perform the work
134 * <p>see also @ref getRequiredResource, @ref getRequiredResource
135 */
136 void addRequiredResource( ResourceGroup* );
137 /** Manage the dependent resources. This is a list of the resource
138 * groups that must have available resources for this resource to
139 * perform the work
140 * <p>see also @ref addRequiredResource, @ref getRequiredResource
141 */
142 ResourceGroup* getRequiredResource( int );
143 /** Manage the dependent resources. This is a list of the resource
144 * groups that must have available resources for this resource to
145 * perform the work
146 * <p>see also @ref getRequiredResource, @ref addRequiredResource
147 */
148 void deleteRequiredResource( int );
149
150 bool load( KoXmlElement &element, XMLLoaderObject &status );
151 void save( QDomElement &element ) const;
152
153 /// Save workpackage document. Include only resources listed in @p lst
154 void saveWorkPackageXML( QDomElement &element, const QList<Resource*> lst ) const;
155
156 void initiateCalculation( Schedule &sch );
157
158 void addNode( Node *node ) { m_nodes.append( node ); }
159 void clearNodes() { m_nodes.clear(); }
160
161 Calendar *defaultCalendar() { return m_defaultCalendar; }
162
163 int units() const;
164
165 void registerRequest( ResourceGroupRequest *request )
166 { m_requests.append( request ); }
167 void unregisterRequest( ResourceGroupRequest *request )
168 {
169 int i = m_requests.indexOf( request );
170 if ( i != -1 )
171 m_requests.removeAt( i );
172 }
173 const QList<ResourceGroupRequest*> &requests() const
174 { return m_requests; }
175
176 ResourceGroup *findId() const { return findId( m_id ); }
177 ResourceGroup *findId( const QString &id ) const;
178 bool removeId() { return removeId( m_id ); }
179 bool removeId( const QString &id );
180 void insertId( const QString &id );
181
182 Appointment appointmentIntervals() const;
183
184 // m_project is set when the resourcegroup is added to the project,
185 // and reset when the resourcegroup is removed from the project
186 void setProject( Project *project );
187
188 void copy( const ResourceGroup *group );
189
190 DateTime startTime( long id ) const;
191 DateTime endTime( long id ) const;
192
193#ifndef NDEBUG
194
195 void printDebug( const QString& ident );
196#endif
197
198protected:
199 virtual void changed();
200
201private:
202 Project *m_project;
203 QString m_id; // unique id
204 QString m_name;
205 QList<Resource*> m_resources;
206 QList<Risk*> m_risks;
207 QList<ResourceGroup*> m_requires;
208
209 QList<Node*> m_nodes; //The nodes that want resources from us
210
211 Calendar *m_defaultCalendar;
212 Type m_type;
213
214 QList<ResourceGroupRequest*> m_requests;
215
216};
217
218/**
219 * Any resource that is used by a task. A resource can be a worker, or maybe wood.
220 * If the resources is a worker or a piece of equiment which can be reused but
221 * can only be used by one node in time, then we can use the scheduling methods of the
222 * resource to schedule the resource available time for the project.
223 * The Idea is that all nodes which need this resource point to it and the scheduling
224 * code (partly implemented here) schedules the actual usage.
225 * See also @ref ResourceGroup
226 */
227
228class KPLATOKERNEL_EXPORT Resource : public QObject
229{
230 Q_OBJECT
231public:
232
233 Resource();
234 explicit Resource(Resource *resource);
235 virtual ~Resource();
236
237 QString id() const { return m_id; }
238 void setId( const QString& id );
239
240 enum Type { Type_Work, Type_Material, Type_Team };
241 void setType( Type type );
242 void setType( const QString &type );
243 Type type() const { return m_type; }
244 QString typeToString( bool trans = false ) const;
245 static QStringList typeToStringList( bool trans = false );
246
247 void setName( const QString &n );
248 const QString &name() const { return m_name;}
249
250 void setInitials( const QString &initials );
251 const QString &initials() const { return m_initials;}
252
253 void setEmail( const QString &email );
254 const QString &email() const { return m_email;}
255
256 /// Returns true if this resource will be allocated by default to new tasks
257 bool autoAllocate() const;
258 /// Set if this resource will be allocated by default to new tasks
259 void setAutoAllocate( bool on );
260
261 void copy( Resource *resource );
262
263 void setParentGroup( ResourceGroup *parent ) { m_parent = parent; }
264 ResourceGroup *parentGroup() const { return m_parent; }
265
266 /// Set the time from when the resource is available to this project
267 void setAvailableFrom( const QDateTime &af ) { m_availableFrom = af; changed();}
268 /// Set the time from when the resource is available to this project
269 void setAvailableFrom( const DateTime &af ) { m_availableFrom = af; changed(); }
270 /// Return the time when the resource is available to this project
271 const DateTime &availableFrom() const { return m_availableFrom;}
272 /// Set the time when the resource is no longer available to this project
273 void setAvailableUntil( const QDateTime &au ) { m_availableUntil = au; changed(); }
274 /// Set the time when the resource is no longer available to this project
275 void setAvailableUntil( const DateTime &au ) { m_availableUntil = au; changed(); }
276 /// Return the time when the resource is no longer available to this project.
277 const DateTime &availableUntil() const { return m_availableUntil;}
278
279 DateTime firstAvailableAfter( const DateTime &time, const DateTime &limit ) const;
280
281 DateTime getBestAvailableTime( const Duration &duration );
282 DateTime getBestAvailableTime( const DateTime &after, const Duration &duration );
283
284 bool load( KoXmlElement &element, XMLLoaderObject &status );
285 void save( QDomElement &element ) const;
286
287 /// Return the list of appointments for schedule @p id.
288 QList<Appointment*> appointments( long id = -1 ) const;
289 /// Return the number of appointments (nodes)
290 int numAppointments( long id = -1 ) const { return appointments( id ).count(); }
291 /// Return the appointment at @p index for schedule @p id
292 Appointment *appointmentAt( int index, long id = -1 ) const { return appointments( id ).value( index ); }
293 int indexOf( Appointment *a, long id = -1 ) const { return appointments( id ).indexOf( a ); }
294
295 /// Adds appointment to current schedule
296 virtual bool addAppointment( Appointment *appointment );
297 /// Adds appointment to schedule sch
298 virtual bool addAppointment( Appointment *appointment, Schedule &main );
299 /// Adds appointment to both this resource and node
300 virtual void addAppointment( Schedule *node, const DateTime &start, const DateTime &end, double load = 100 );
301
302 void initiateCalculation( Schedule &sch );
303 bool isAvailable( Task *task );
304 void makeAppointment( Schedule *schedule, int load, const QList<Resource*> &required = QList<Resource*>() );
305
306 bool isOverbooked() const;
307 /// check if overbooked on date.
308 bool isOverbooked( const QDate &date ) const;
309 /// check if overbooked within the interval start, end.
310 bool isOverbooked( const DateTime &start, const DateTime &end ) const;
311
312 double normalRate() const { return cost.normalRate; }
313 void setNormalRate( double rate ) { cost.normalRate = rate; changed(); }
314 double overtimeRate() const { return cost.overtimeRate; }
315 void setOvertimeRate( double rate ) { cost.overtimeRate = rate; changed(); }
316
317 /**
318 * Return available units in percent
319 */
320 int units() const { return m_units; }
321 /**
322 * Set available units in percent
323 */
324 void setUnits( int units );
325
326 Project *project() const { return m_project; }
327 /// Return the resources timespec. Defaults to local.
328 KDateTime::Spec timeSpec() const;
329
330 /**
331 * Get the calendar for this resource.
332 * Working resources may have a default calendar if the a calendar is marked as default,
333 * this is checked if local=false.
334 * If no calendar can be found for a working resource, the resource is not available.
335 *
336 * Material resources must have calendar explicitly set.
337 * If there is no calendar set for a material resource, the resource is always available.
338 */
339 Calendar *calendar( bool local = false ) const;
340 //Calendar *calendar( const QString& id ) const;
341 void setCalendar( Calendar *calendar );
342
343 /// Delete all requests for me
344 void removeRequests();
345 /**
346 * Used to clean up requests when the resource is deleted.
347 */
348 void registerRequest( ResourceRequest *request )
349 { m_requests.append( request ); }
350 void unregisterRequest( ResourceRequest *request )
351 {
352 int i = m_requests.indexOf( request );
353 if ( i != -1 )
354 m_requests.removeAt( i );
355 }
356 const QList<ResourceRequest*> &requests() const
357 { return m_requests; }
358
359 /// Returns a list of work intervals in the interval @p from, @p until.
360 /// Appointments are subtracted if @p schedule is not 0 and overbooking is not allowed.
361 AppointmentIntervalList workIntervals( const DateTime &from, const DateTime &until, Schedule *schedule ) const;
362
363 /// Returns a list of work intervals in the interval @p from, @p until.
364 AppointmentIntervalList workIntervals( const DateTime &from, const DateTime &until ) const;
365
366 /// Updates work interval cache a list of work intervals extracted from the resource calendar
367 /// with @p load in the interval @p from, @p until.
368 /// The load of the intervals is set to m_units
369 /// Note: The list may contain intervals outside @p from, @p until
370 void calendarIntervals( const DateTime &from, const DateTime &until ) const;
371 /// Load cache from @p element
372 bool loadCalendarIntervalsCache( const KoXmlElement& element, KPlato::XMLLoaderObject& status );
373 /// Save cache to @p element
374 void saveCalendarIntervalsCache( QDomElement &element ) const;
375
376 /// Returns the effort that can be done starting at @p start within @p duration.
377 /// The current schedule is used to check for appointments.
378 /// If @p backward is true, checks backward in time.
379 Duration effort( const DateTime &start, const Duration &duration, int units = 100, bool backward = false, const QList<Resource*> &required = QList<Resource*>() ) const;
380
381 /// Returns the effort that can be done starting at @p start within @p duration.
382 /// The schedule @p sch is used to check for appointments.
383 /// If @p backward is true, checks backward in time.
384 /// Status is returned in @p ok
385 Duration effort( KPlato::Schedule* sch, const DateTime &start, const Duration& duration, int units = 100, bool backward = false, const QList< Resource* >& required = QList<Resource*>() ) const;
386
387
388 /**
389 * Find the first available time after @p time, within @p limit.
390 * Returns invalid DateTime if not available.
391 * Uses the current schedule to check for appointments.
392 */
393 DateTime availableAfter( const DateTime &time, const DateTime limit = DateTime() ) const;
394 /**
395 * Find the first available time before @p time, within @p limit.
396 * Returns invalid DateTime if not available.
397 * Uses the current schedule to check for appointments.
398 */
399 DateTime availableBefore( const DateTime &time, const DateTime limit = DateTime()) const;
400
401 /**
402 * Find the first available time after @p time, within @p limit.
403 * Returns invalid DateTime if not available.
404 * If @p sch == 0, Appointments are not checked.
405 */
406 DateTime availableAfter( const DateTime &time, const DateTime limit, Schedule *sch ) const;
407 /**
408 * Find the first available time before @p time, within @p limit.
409 * Returns invalid DateTime if not available.
410 * If @p sch == 0, Appointments are not checked.
411 */
412 DateTime availableBefore( const DateTime &time, const DateTime limit, Schedule *sch ) const;
413
414 Resource *findId() const { return findId( m_id ); }
415 Resource *findId( const QString &id ) const;
416 bool removeId() { return removeId( m_id ); }
417 bool removeId( const QString &id );
418 void insertId( const QString &id );
419
420 Calendar *findCalendar( const QString &id ) const;
421
422 Appointment appointmentIntervals( long id ) const;
423 Appointment appointmentIntervals() const;
424
425 EffortCostMap plannedEffortCostPrDay( const QDate &start, const QDate &end, long id, EffortCostCalculationType = ECCT_All );
426 Duration plannedEffort( const QDate &date, EffortCostCalculationType = ECCT_All ) const;
427
428 void setCurrentSchedulePtr( Schedule *schedule ) { m_currentSchedule = schedule; }
429 void setCurrentSchedule( long id ) { m_currentSchedule = findSchedule( id ); }
430 Schedule *currentSchedule() const { return m_currentSchedule; }
431
432 bool isScheduled() const;
433 QHash<long, Schedule*> schedules() const { return m_schedules; }
434 /**
435 * Return schedule with @id
436 * If @p id == CURRENTSCHEDULE, return m_currentSchedule
437 * Return 0 if schedule with @p id doesn't exist.
438 */
439 Schedule *schedule( long id = CURRENTSCHEDULE ) const;
440 /// Returns true if schedule with @p id is baselined.
441 /// if Team resource, if any of the team members is baselined
442 /// By default returns true if any schedule is baselined
443 bool isBaselined( long id = BASELINESCHEDULE ) const;
444 /**
445 * Return schedule with @id
446 * Return 0 if schedule with @id doesn't exist.
447 */
448 Schedule *findSchedule( long id ) const;
449 /// Take, and delete.
450 void deleteSchedule( Schedule *schedule );
451 /// Take, don't delete.
452 void takeSchedule( const Schedule *schedule );
453 void addSchedule( Schedule *schedule );
454 ResourceSchedule *createSchedule( const QString& name, int type, long id );
455 ResourceSchedule *createSchedule( Schedule *parent );
456
457 // m_project is set when the resource (or the parent) is added to the project,
458 // and reset when the resource is removed from the project
459 void setProject( Project *project );
460
461 void addExternalAppointment( const QString &id, Appointment *a );
462
463 void addExternalAppointment( const QString &id, const QString &name, const DateTime &from, const DateTime &end, double load = 100 );
464 void subtractExternalAppointment( const QString &id, const DateTime &from, const DateTime &end, double load );
465
466 void clearExternalAppointments();
467 void clearExternalAppointments( const QString id );
468 /// Take the external appointments with identity @p id from the list of external appointments
469 Appointment *takeExternalAppointment( const QString &id );
470 /// Return external appointments with identity @p id
471 AppointmentIntervalList externalAppointments( const QString &id );
472 AppointmentIntervalList externalAppointments( const DateTimeInterval &interval = DateTimeInterval() ) const;
473
474 int numExternalAppointments() const { return m_externalAppointments.count(); }
475 QList<Appointment*> externalAppointmentList() const { return m_externalAppointments.values(); }
476 /// return a map of project id, project name
477 QMap<QString, QString> externalProjects() const;
478
479 /// Return a measure of how suitable the resource is for allocation
480 long allocationSuitability( const DateTime &time, const Duration &duration, bool backward );
481
482 DateTime startTime( long id ) const;
483 DateTime endTime( long id ) const;
484
485 /// Returns the list of requiered resources.
486 /// Note: This list is used as default for allocation dialog, not for scheduling.
487 QList<Resource*> requiredResources() const;
488 /// Set the list of the required resources's ids so they can be resolved when used
489 /// A required resource may not exist in the project yet
490 void setRequiredIds( const QStringList &lst );
491 /// Add a resource id to the required ids list
492 void addRequiredId( const QString &id );
493 /// Returns the list of requiered resource ids.
494 QStringList requiredIds() const { return m_requiredIds; }
495
496 /// Return the list of team members.
497 QList<Resource*> teamMembers() const;
498 /// Return the list of team members.
499 QStringList teamMemberIds() const;
500 /// Clear the list of team members.
501 void clearTeamMembers() { m_teamMembers.clear(); }
502 /// Add resource @p id to the list of team members.
503 void addTeamMemberId( const QString &id );
504 /// Remove resource @p id from the list of team members.
505 void removeTeamMemberId( const QString &id );
506
507 /// Return the account
508 Account *account() const { return cost.account; }
509 /// Set the @p account
510 void setAccount( Account *account );
511
512 // for xml loading code
513
514 class WorkInfoCache
515 {
516 public:
517 WorkInfoCache() { clear(); }
518 void clear() { start = end = DateTime(); effort = Duration::zeroDuration; intervals.clear(); version = -1; }
519 bool isValid() const { return start.isValid() && end.isValid(); }
520 DateTime firstAvailableAfter( const DateTime &time, const DateTime &limit, Calendar *cal, Schedule *sch ) const;
521 DateTime firstAvailableBefore( const DateTime &time, const DateTime &limit, Calendar *cal, Schedule *sch ) const;
522
523 DateTime start;
524 DateTime end;
525 Duration effort;
526 AppointmentIntervalList intervals;
527 int version;
528
529 bool load( const KoXmlElement& element, KPlato::XMLLoaderObject& status );
530 void save( QDomElement &element ) const;
531 };
532 const WorkInfoCache &workInfoCache() const { return m_workinfocache; }
533
534signals:
535 void externalAppointmentToBeAdded( Resource *r, int row );
536 void externalAppointmentAdded( Resource*, Appointment* );
537 void externalAppointmentToBeRemoved( Resource *r, int row );
538 void externalAppointmentRemoved();
539 void externalAppointmentChanged( Resource *r, Appointment *a );
540
541protected:
542 DateTimeInterval requiredAvailable(Schedule *node, const DateTime &start, const DateTime &end ) const;
543 void makeAppointment( Schedule *node, const DateTime &from, const DateTime &end, int load, const QList<Resource*> &required = QList<Resource*>() );
544 virtual void changed();
545
546private:
547 Project *m_project;
548 ResourceGroup *m_parent;
549 QHash<long, Schedule*> m_schedules;
550 QString m_id; // unique id
551 QString m_name;
552 QString m_initials;
553 QString m_email;
554 bool m_autoAllocate;
555 DateTime m_availableFrom;
556 DateTime m_availableUntil;
557 QMap<QString, Appointment*> m_externalAppointments;
558
559 int m_units; // avalable units in percent
560
561 Type m_type;
562
563 struct Cost
564 {
565 double normalRate;
566 double overtimeRate;
567 double fixed ;
568 Account *account;
569 }
570 cost;
571
572 Calendar *m_calendar;
573 QList<ResourceRequest*> m_requests;
574 QStringList m_requiredIds;
575
576 QStringList m_teamMembers;
577
578 Schedule *m_currentSchedule;
579
580 mutable WorkInfoCache m_workinfocache;
581
582 // return this if resource has no calendar and is a material resource
583 Calendar m_materialCalendar;
584
585#ifndef NDEBUG
586public:
587 void printDebug( const QString& ident );
588#endif
589};
590
591KPLATOKERNEL_EXPORT QDebug operator<<( QDebug dbg, const KPlato::Resource::WorkInfoCache &c );
592
593/**
594 * Risk is associated with a resource/task pairing to indicate the planner's confidence in the
595 * estimated effort. Risk can be one of none, low, or high. Some factors that may be taken into
596 * account for risk are the experience of the person and the reliability of equipment.
597 */
598class Risk
599{
600public:
601
602 enum RiskType {
603 NONE = 0,
604 LOW = 1,
605 HIGH = 2
606 };
607
608 Risk( Node *n, Resource *r, RiskType rt = NONE );
609 ~Risk();
610
611 RiskType riskType() { return m_riskType; }
612
613 Node *node() { return m_node; }
614 Resource *resource() { return m_resource; }
615
616private:
617 Node *m_node;
618 Resource *m_resource;
619 RiskType m_riskType;
620};
621
622class KPLATOKERNEL_EXPORT ResourceRequest
623{
624public:
625 explicit ResourceRequest( Resource *resource = 0, int units = 1 );
626 explicit ResourceRequest( const ResourceRequest &r );
627
628 ~ResourceRequest();
629
630 ResourceGroupRequest *parent() const { return m_parent; }
631 void setParent( ResourceGroupRequest *parent ) { m_parent = parent; }
632
633 Resource *resource() const { return m_resource; }
634 void setResource( Resource* resource ) { m_resource = resource; }
635
636 bool load( KoXmlElement &element, Project &project );
637 void save( QDomElement &element ) const;
638
639 /**
640 * Get amount of requested resource units in percent
641 */
642 int units() const;
643 void setUnits( int value );
644
645 void registerRequest()
646 {
647 if ( m_resource )
648 m_resource->registerRequest( this );
649 }
650 void unregisterRequest()
651 {
652 if ( m_resource )
653 m_resource->unregisterRequest( this );
654 }
655
656 void makeAppointment( Schedule *schedule, int amount );
657 void makeAppointment( Schedule *schedule );
658 Task *task() const;
659
660 /// Return the datetime from when the resource is available.
661 /// If it is not valid, the project constraint start time is used.
662 /// For teams the earliest time for any team member is used.
663 DateTime availableFrom();
664 /// Return the datetime until when the resource is available.
665 /// If it is not valid, the project constraint end time is used.
666 /// For teams the latest time for any team member is used.
667 DateTime availableUntil();
668
669 Schedule *resourceSchedule( Schedule *ns, Resource *resource = 0 );
670 DateTime availableAfter(const DateTime &time, Schedule *ns);
671 DateTime availableBefore(const DateTime &time, Schedule *ns);
672 Duration effort( const DateTime &time, const Duration &duration, Schedule *ns, bool backward );
673 DateTime workTimeAfter(const DateTime &dt, Schedule *ns = 0);
674 DateTime workTimeBefore(const DateTime &dt, Schedule *ns = 0);
675
676 /// Resource is allocated dynamically by the group request
677 bool isDynamicallyAllocated() const { return m_dynamic; }
678 /// Set resource is allocated dynamically
679 void setAllocatedDynaically( bool dyn ) { m_dynamic = dyn; }
680
681 /// Return a measure of how suitable the resource is for allocation
682 long allocationSuitability( const DateTime &time, const Duration &duration, Schedule *ns, bool backward );
683
684 /// Returns a list of all the required resources that will be used in scheduling.
685 /// Note: This list overrides the resources own list which is just used as default for allocation dialog.
686 QList<Resource*> requiredResources() const { return m_required; }
687 /// Set the list of required resources that will be used in scheduling.
688 void setRequiredResources( const QList<Resource*> &lst ) { m_required = lst; }
689
690private:
691 friend class ResourceGroupRequest;
692 QList<ResourceRequest*> teamMembers() const;
693
694protected:
695 void changed();
696
697 void setCurrentSchedulePtr( Schedule *ns );
698 void setCurrentSchedulePtr( Resource *resource, Schedule *ns );
699
700private:
701 Resource *m_resource;
702 int m_units;
703 ResourceGroupRequest *m_parent;
704 bool m_dynamic;
705 QList<Resource*> m_required;
706 mutable QList<ResourceRequest*> m_teamMembers;
707
708#ifndef NDEBUG
709public:
710 void printDebug( const QString& ident );
711#endif
712};
713QDebug &operator<<( QDebug &dbg, const KPlato::ResourceRequest *r );
714QDebug &operator<<( QDebug &dbg, const KPlato::ResourceRequest &r );
715
716class KPLATOKERNEL_EXPORT ResourceGroupRequest
717{
718public:
719 explicit ResourceGroupRequest( ResourceGroup *group = 0, int units = 0 );
720 explicit ResourceGroupRequest( const ResourceGroupRequest &group );
721 ~ResourceGroupRequest();
722
723 void setParent( ResourceRequestCollection *parent ) { m_parent = parent;}
724 ResourceRequestCollection *parent() const { return m_parent; }
725
726 ResourceGroup *group() const { return m_group; }
727 void setGroup( ResourceGroup *group ) { m_group = group; }
728 void unregister( const ResourceGroup *group ) { if ( group == m_group ) m_group = 0; }
729 /// Return a list of resource requests.
730 /// If @p resolveTeam is true, include the team members,
731 /// if @p resolveTeam is false, include the team resource itself.
732 QList<ResourceRequest*> resourceRequests( bool resolveTeam=true ) const;
733 void addResourceRequest( ResourceRequest *request );
734 void deleteResourceRequest( ResourceRequest *request );
735 int count() const { return m_resourceRequests.count(); }
736 ResourceRequest *requestAt( int idx ) const { return m_resourceRequests.value( idx ); }
737
738 ResourceRequest *takeResourceRequest( ResourceRequest *request );
739 ResourceRequest *find( const Resource *resource ) const;
740 ResourceRequest *resourceRequest( const QString &name );
741 /// Return a list of allocated resources, allocation to group is not included by default.
742 QStringList requestNameList( bool includeGroup = false ) const;
743 /// Return a list of allocated resources.
744 /// Allocations to groups are not included.
745 /// Team resources are included but *not* the team members.
746 /// Any dynamically allocated resource is not included.
747 QList<Resource*> requestedResources() const;
748 bool load( KoXmlElement &element, XMLLoaderObject &status );
749 void save( QDomElement &element ) const;
750
751 /// The number of requested resources
752 int units() const;
753 void setUnits( int value ) { m_units = value; changed(); }
754
755 /**
756 * Returns the duration needed to do the @p effort starting at @p start.
757 */
758 Duration duration( const DateTime &start, const Duration &effort, Schedule *ns, bool backward = false );
759
760 DateTime availableAfter( const DateTime &time, Schedule *ns );
761 DateTime availableBefore( const DateTime &time, Schedule *ns );
762 DateTime workTimeAfter(const DateTime &dt, Schedule *ns = 0);
763 DateTime workTimeBefore(const DateTime &dt, Schedule *ns = 0);
764
765 /**
766 * Makes appointments for task @param task to the
767 * requested resources for the duration found in @ref duration().
768 */
769 void makeAppointments( Schedule *schedule );
770
771 /**
772 * Reserves the requested resources for the specified interval
773 */
774 void reserve( const DateTime &start, const Duration &duration );
775
776 bool isEmpty() const;
777
778 Task *task() const;
779
780 void changed();
781
782 /// Reset dynamic resource allocations
783 void resetDynamicAllocations();
784 /// Allocate dynamic requests. Do nothing if already allocated.
785 void allocateDynamicRequests( const DateTime &time, const Duration &effort, Schedule *ns, bool backward );
786
787private:
788 ResourceGroup *m_group;
789 int m_units;
790 ResourceRequestCollection *m_parent;
791
792 QList<ResourceRequest*> m_resourceRequests;
793 DateTime m_start;
794 Duration m_duration;
795
796#ifndef NDEBUG
797public:
798 void printDebug( const QString& ident );
799#endif
800};
801
802class KPLATOKERNEL_EXPORT ResourceRequestCollection
803{
804public:
805 explicit ResourceRequestCollection( Task *task = 0 );
806 ~ResourceRequestCollection();
807
808 QList<ResourceGroupRequest*> requests() const { return m_requests; }
809 void addRequest( ResourceGroupRequest *request );
810 void deleteRequest( ResourceGroupRequest *request )
811 {
812 int i = m_requests.indexOf( request );
813 if ( i != -1 )
814 m_requests.removeAt( i );
815 delete request;
816 changed();
817 }
818
819 int takeRequest( ResourceGroupRequest *request )
820 {
821 int i = m_requests.indexOf( request );
822 if ( i != -1 ) {
823 m_requests.removeAt( i );
824 changed();
825 }
826 return i;
827 }
828
829 ResourceGroupRequest *find( const ResourceGroup *resource ) const;
830 ResourceRequest *find( const Resource *resource ) const;
831 ResourceRequest *resourceRequest( const QString &name ) const;
832 /// The ResourceRequestCollection has no requests
833 bool isEmpty() const;
834 /// Empty the ResourceRequestCollection of all requets
835 void clear() { m_requests.clear(); }
836 /// Reset dynamic resource allocations
837 void resetDynamicAllocations();
838
839 bool contains( const QString &identity ) const;
840 ResourceGroupRequest *findGroupRequestById( const QString &id ) const;
841 /// Return a list of names of allocated resources.
842 /// Allocations to groups are not included by default.
843 /// Team resources are included but *not* the team members.
844 /// Any dynamically allocated resource is not included.
845 QStringList requestNameList( bool includeGroup = false ) const;
846 /// Return a list of allocated resources.
847 /// Allocations to groups are not included.
848 /// Team resources are included but *not* the team members.
849 /// Any dynamically allocated resource is not included.
850 QList<Resource*> requestedResources() const;
851
852 /// Return a list of all resource requests.
853 /// If @p resolveTeam is true, include the team members,
854 /// if @p resolveTeam is false, include the team resource itself.
855 QList<ResourceRequest*> resourceRequests( bool resolveTeam=true ) const;
856
857 //bool load(KoXmlElement &element, Project &project);
858 void save( QDomElement &element ) const;
859
860 /**
861 * Returns the duration needed to do the @p effort starting at @p time.
862 */
863 Duration duration( const DateTime &time, const Duration &effort, Schedule *sch, bool backward = false );
864
865 DateTime availableAfter( const DateTime &time, Schedule *ns );
866 DateTime availableBefore( const DateTime &time, Schedule *ns );
867 DateTime workTimeAfter(const DateTime &dt, Schedule *ns = 0) const;
868 DateTime workTimeBefore(const DateTime &dt, Schedule *ns = 0) const;
869 DateTime workStartAfter(const DateTime &time, Schedule *ns);
870 DateTime workFinishBefore(const DateTime &time, Schedule *ns);
871
872 /**
873 * Makes appointments for the task @param task to the requested resources.
874 * Assumes that @ref duration() has been run.
875 */
876 void makeAppointments( Schedule *schedule );
877 /**
878 * Reserves the requested resources for the specified interval
879 */
880 void reserve( const DateTime &start, const Duration &duration );
881
882 Task *task() const { return m_task; }
883 void setTask( Task *t ) { m_task = t; }
884
885 void changed();
886
887 Duration effort( const QList<ResourceRequest*> &lst, const DateTime &time, const Duration &duration, Schedule *ns, bool backward ) const;
888 int numDays(const QList<ResourceRequest*> &lst, const DateTime &time, bool backward) const;
889 Duration duration(const QList<ResourceRequest*> &lst, const DateTime &time, const Duration &_effort, Schedule *ns, bool backward);
890
891private:
892 Task *m_task;
893 QList<ResourceGroupRequest*> m_requests;
894};
895
896} //KPlato namespace
897
898#endif
899