Merge branch '2013.10' into 2014.11
[tine20] / tine20 / Timetracker / Setup / DemoData.php
1 <?php
2 /**
3  * Tine 2.0
4  *
5  * @package     Timetracker
6  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
7  * @author      Alexander Stintzing <a.stintzing@metaways.de>
8  * @copyright   Copyright (c) 2013 Metaways Infosystems GmbH (http://www.metaways.de)
9  *
10  */
11
12 /**
13  * class for Timetracker initialization
14  *
15  * @package     Setup
16  */
17 class Timetracker_Setup_DemoData extends Tinebase_Setup_DemoData_Abstract
18 {
19     /**
20      * required apps
21      * 
22      * @var array
23      */
24     protected static $_requiredApplications = array('Admin', 'Sales');
25     
26     /**
27      * holds the instance of the singleton
28      *
29      * @var Timetracker_Setup_DemoData
30      */
31     private static $_instance = NULL;
32     
33     /**
34      * the application name to work on
35      * 
36      * @var string
37      */
38     protected $_appName = 'Timetracker';
39     
40     /**
41      * @var Timetracker_Controller_Timeaccount
42      */
43     protected $_taController;
44     
45     /**
46      * 
47      * @var Tinebase_DateTime
48      */
49     protected $_startDate;
50     
51     /**
52      * @var Timetracker_Controller_Timesheet
53      */
54     protected $_tsController;
55     
56     /**
57      * @var Tinebase_DateTime
58      */
59     protected $_clearedDate;
60     
61     /**
62      * RecordSet with all employees
63      *
64      * @var Tinebase_Record_RecordSet
65      */
66     protected $_employees;
67     
68     /**
69      * @var HumanResources_Controller_Employee
70      */
71     protected $_empController;
72     
73     /**
74      * array of RecordSets with all timetracker.timeaccounts
75      *
76      * @var Tinebase_Record_RecordSet
77      */
78     protected $_timeAccounts;
79     
80     /**
81      * array of RecordSets with all contracts having the development costcenter assigned
82      *
83      * @var Tinebase_Record_RecordSet
84      */
85     protected $_contractsDevelopment;
86
87     /**
88      * array of RecordSets with all contracts having the marketing costcenter assigned
89      *
90      * @var Tinebase_Record_RecordSet
91      */
92     protected $_contractsMarketing;
93     
94     /**
95      * cc controller
96      * 
97      * @var Sales_Controller_CostCenter
98      */
99     protected $_ccController;
100     
101     /**
102      * The contract controller
103      * 
104      * @var Sales_Controller_Contract
105      */
106     protected $_contractController = NULL;
107     
108     /**
109      * models to work on
110      * 
111      * @var array
112      */
113     protected $_models = array('timeaccount', 'timesheet');
114     
115     /**
116      * the constructor
117      *
118      */
119     private function __construct()
120     {
121     }
122
123     /**
124      * the singleton pattern
125      *
126      * @return Timetracker_Setup_DemoData
127      */
128     public static function getInstance()
129     {
130         if (self::$_instance === NULL) {
131             self::$_instance = new self();
132         }
133         
134         return self::$_instance;
135     }
136
137     /**
138      * this is required for other applications needing demo data of this application
139      * if this returns true, this demodata has been run already
140      * 
141      * @return boolean
142      */
143     public static function hasBeenRun()
144     {
145         $c = Timetracker_Controller_Timeaccount::getInstance();
146         
147         $f = new Timetracker_Model_TimeaccountFilter(array(
148             array('field' => 'description', 'operator' => 'equals', 'value' => 'Created By Tine 2.0 DemoData'),
149         ), 'AND');
150         
151         return ($c->search($f)->count() > 9) ? true : false;
152     }
153     
154     /**
155      * @see Tinebase_Setup_DemoData_Abstract
156      * 
157      */
158     protected function _beforeCreate()
159     {
160         $this->_ccController  = Sales_Controller_CostCenter::getInstance();
161         $this->_taController  = Timetracker_Controller_Timeaccount::getInstance();
162         $this->_taController->sendNotifications(FALSE);
163         $this->_tsController  = Timetracker_Controller_Timesheet::getInstance();
164         $this->_tsController->sendNotifications(FALSE);
165         $this->_tsController->doContainerACLChecks(false);
166         
167         $this->_contractController    = Sales_Controller_Contract::getInstance();
168         $contracts = $this->_contractController->getAll();
169         $developmentString = self::$_de ? 'Entwicklung' : 'Development';
170         
171         $this->_contractsDevelopment = $contracts->filter('title', '/.' . $developmentString . '/', TRUE);
172         $this->_contractsMarketing = $contracts->filter('title', '/.Marketing/', TRUE);
173         
174         $this->_loadCostCentersAndDivisions();
175         
176         if (Tinebase_Application::getInstance()->isInstalled('HumanResources')) {
177             $this->_empController = HumanResources_Controller_Employee::getInstance();
178             $filter = new HumanResources_Model_EmployeeFilter(array());
179             $this->_employees = $this->_empController->search($filter);
180         }
181         
182         // set start date to start date of june 1st before last year
183         $date = Tinebase_DateTime::now();
184         $this->_startDate = $date->subMonth(3)->setTime(8,0,0);
185
186         // set clearedDate almost a month after
187         $this->_clearedDate = clone $this->_startDate;
188         $this->_clearedDate->addMonth(1)->subDay(2);
189     }
190     
191     /**
192      * creates shared tas
193      */
194     protected function _createSharedTimeaccounts()
195     {
196         // create 2 timeaccounts for each cc
197         $taNumber = 1;
198         
199         $userGroup = Tinebase_Group::getInstance()->getGroupByName('Users');
200         $developmentString = self::$_de ? 'Entwicklung' : 'Development';
201         if (! $userGroup) {
202             die('Could not find userGroup "Users", stopping.');
203         }
204         
205         $grants = array(array(
206             'account_id' => $userGroup->getId(),
207             'account_type' => 'group',
208             'bookOwnGrant' => TRUE,
209             'viewAllGrant' => TRUE,
210             'bookAllGrant' => TRUE,
211             // TODO: this shouldn't be neccessary, but is. why?:
212             'manageBillableGrant' => TRUE,
213             'exportGrant' => TRUE,
214             'adminGrant' => TRUE
215         ));
216         
217         $contractsIndex = 0;
218         
219         foreach($this->_costCenters as $costcenter) {
220             
221             $this->_timeAccounts[$costcenter->getId()] = new Tinebase_Record_RecordSet('Timetracker_Model_Timeaccount');
222             $i=0;
223             
224             while ($i < 2) {
225                 $i++;
226                 
227                 $ta = new Timetracker_Model_Timeaccount(array(
228                     'number'      => $taNumber,
229                     'title'       => Tinebase_Record_Abstract::generateUID(3),
230                     'grants'      => $grants,
231                     'status'      => 'billed',
232                     'cleared_at'  => $this->_clearedDate,
233                     'budget'      => NULL,
234                     'description' => 'Created By Tine 2.0 DEMO DATA'
235                 ));
236                 
237                 if (($costcenter->remark == 'Marketing') || ($costcenter->remark == $developmentString)) {
238                     $contract = $costcenter->remark == 'Marketing' ? $this->_contractsMarketing->getByIndex(rand(0, ($this->_contractsMarketing->count() -1))) : $this->_contractsDevelopment->getByIndex(rand(0, ($this->_contractsDevelopment->count() -1)));
239                     
240                     $ta->budget = $costcenter->remark == 'Marketing' ? 100 : NULL;
241                     $ta->relations = array(
242                         array(
243                             'own_model'              => 'Timetracker_Model_Timeaccount',
244                             'own_backend'            => 'SQL',
245                             'own_id'                 => NULL,
246                             'own_degree'             => Tinebase_Model_Relation::DEGREE_SIBLING,
247                             'related_model'          => 'Sales_Model_CostCenter',
248                             'related_backend'        => Tasks_Backend_Factory::SQL,
249                             'related_id'             => $costcenter->getId(),
250                             'type'                   => 'COST_CENTER'
251                         ),
252                         array(
253                             'own_model'              => 'Timetracker_Model_Timeaccount',
254                             'own_backend'            => 'SQL',
255                             'own_id'                 => NULL,
256                             'own_degree'             => Tinebase_Model_Relation::DEGREE_SIBLING,
257                             'related_model'          => 'Sales_Model_Contract',
258                             'related_backend'        => Tasks_Backend_Factory::SQL,
259                             'related_id'             => $contract->getId(),
260                             'type'                   => 'TIME_ACCOUNT'
261                         ));
262                     $ta->title = (self::$_de ? 'Zeitkonto mit ' : 'Timeaccount for ') . $contract->getTitle();
263                 } else {
264                     $ta->title = (self::$_de ? 'Zeitkonto mit KST ' : 'Timeaccount for CC ') . $costcenter->getTitle();
265                     $ta->relations = array(
266                         array(
267                             'own_model'              => 'Timetracker_Model_Timeaccount',
268                             'own_backend'            => 'SQL',
269                             'own_id'                 => NULL,
270                             'own_degree'             => Tinebase_Model_Relation::DEGREE_SIBLING,
271                             'related_model'          => 'Sales_Model_CostCenter',
272                             'related_backend'        => Tasks_Backend_Factory::SQL,
273                             'related_id'             => $costcenter->getId(),
274                             'type'                   => 'COST_CENTER'
275                         )
276                     );
277                 }
278                 
279                 $this->_timeAccounts[$costcenter->getId()]->addRecord($this->_taController->create($ta));
280                 
281                 $taNumber++;
282             }
283         }
284     }
285     
286     /**
287      * creates and persists a timesheet
288      * 
289      * @param array $data
290      * @return Tinebase_Record_Interface
291      */
292     protected function _createTimesheet($data)
293     {
294         $ts = new Timetracker_Model_Timesheet($data);
295         return $this->_tsController->create($ts);
296     }
297     
298     /**
299      * returns the cost center for the current account
300      */
301     protected function _getCurrentUsersCostCenter()
302     {
303         $employee = $this->_getCurrentUsersEmployee();
304         $salesCC =  HumanResources_Controller_CostCenter::getInstance()->getValidCostCenter($employee->getId(), NULL, TRUE);
305         return $salesCC;
306     }
307     
308     /**
309      * returns the employee for the current account
310      */
311     protected function _getCurrentUsersEmployee()
312     {
313         return $this->_employees->filter('account_id', Tinebase_Core::getUser()->accountId)->getFirstRecord();
314     }
315     
316     /**
317      * creates timesheets
318      */
319     protected function _createTimesheets()
320     {
321         if (Tinebase_Application::getInstance()->isInstalled('HumanResources')) {
322             $cc = $this->_getCurrentUsersCostCenter();
323         } else {
324             $cc = $this->_costCenters->filter('remark', 'Management')->getFirstRecord();
325         }
326         
327         
328         $ownTimeAccountRecordSet = $this->_timeAccounts[$cc->getId()]->sort('number');
329         $userId = Tinebase_Core::getUser()->accountId;
330         
331         $startDate = clone $this->_startDate;
332         $endDate   = clone $startDate;
333         $endDate->addMonth(3);
334         
335         $mkccId = $this->_marketingCostCenter->getId();
336         $deccId = $this->_developmentCostCenter->getId();
337         
338         $allMkccTimeAccountRecordSet = $this->_timeAccounts[$mkccId]->sort('number');
339         $allDeccTimeAccountRecordSet = $this->_timeAccounts[$deccId]->sort('number');
340         
341         $afterCleared = FALSE;
342         $stopIndex = 8;
343         
344         while ($startDate < $endDate) {
345             $wd = (int) $startDate->format('w');
346             
347             // create timesheets from tue -> fri, always a timeaccount of the users costcenter
348             if (($wd < 6) && ($wd > 2)) {
349                 // 8 hrs
350                 $ta = $ownTimeAccountRecordSet->getByIndex(rand(0, ($ownTimeAccountRecordSet->count() - 1)));
351                 $ts = $this->_createTimesheet(array(
352                     'account_id'     => $userId,
353                     'timeaccount_id' => $ta->getId(),
354                     'is_billable'    => false,
355                     'start_date'     => $startDate,
356                     'duration'       => 480,
357                     'description'    => static::$_de ? 'DemoData eigenes Zeitkonto' : 'DemoData own timeaccount',
358                     'is_cleared'     => (($ta->status == 'billed') ? true : false),
359                  ));
360             } else {
361                 
362                 // create timesheets on monday and tuesday
363                 $ta = $allMkccTimeAccountRecordSet->getByIndex(rand(0, ($allMkccTimeAccountRecordSet->count() - 1)));
364                 // 4 hrs for a marketing costcenter timeaccount
365                 $ts = $this->_createTimesheet(array(
366                     'account_id'     => $userId,
367                     'timeaccount_id' => $ta->getId(),
368                     'is_billable'    => false,
369                     'start_date'     => $startDate,
370                     'duration'       => 240,
371                     'description'    => static::$_de ? ('DemoData auf KST ' . $cc->number) : ('DemoData on costcenter ' . $cc->number),
372                     'is_cleared'     => (($ta->status == 'billed') ? true : false),
373                 ));
374                 
375                 $sd = clone $startDate;
376                 $sd->addMinute(300);
377                 $ta = $allDeccTimeAccountRecordSet->getByIndex(rand(0, ($allDeccTimeAccountRecordSet->count() - 1)));
378                 
379                 // 4 hrs for a development costcenter timeaccount
380                 $ts = $this->_createTimesheet(array(
381                     'account_id'     => $userId,
382                     'timeaccount_id' => $ta->getId(),
383                     'is_billable'    => false,
384                     'start_date'     => $sd,
385                     'duration'       => 240,
386                     'description'    => static::$_de ? ('DemoData auf KST ' . $cc->number) : ('DemoData on costcenter ' . $cc->number),
387                     'is_cleared'     => (($ta->status == 'billed') ? true : false),
388                 ));
389             }
390         
391             $startDate->addDay(1);
392         }
393     }
394     
395     /**
396      * @see parent
397      */
398     protected function _createTimesheetsForPwulf()
399     {
400         $this->_createTimesheets();
401     }
402
403     /**
404      * @see parent
405      */
406     protected function _createTimesheetsForRwright()
407     {
408         $this->_createTimesheets();
409     }
410
411     /**
412      * @see parent
413      */
414     protected function _createTimesheetsForSclever()
415     {
416         $this->_createTimesheets();
417     }
418     
419     /**
420      * @see parent
421      */
422     protected function _createTimesheetsForJmcblack()
423     {
424         $this->_createTimesheets();
425     }
426     
427     /**
428      * @see parent
429      */
430     protected function _createTimesheetsForJsmith()
431     {
432         $this->_createTimesheets();
433     }
434 }