Merge branch '2014.11' into 2015.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      * unsets the instance to save memory, be aware that hasBeenRun still needs to work after unsetting!
139      *
140      */
141     public function unsetInstance()
142     {
143         if (self::$_instance !== NULL) {
144             self::$_instance = null;
145         }
146     }
147
148     /**
149      * this is required for other applications needing demo data of this application
150      * if this returns true, this demodata has been run already
151      * 
152      * @return boolean
153      */
154     public static function hasBeenRun()
155     {
156         $c = Timetracker_Controller_Timeaccount::getInstance();
157         
158         $f = new Timetracker_Model_TimeaccountFilter(array(
159             array('field' => 'description', 'operator' => 'equals', 'value' => 'Created By Tine 2.0 DemoData'),
160         ), 'AND');
161         
162         return ($c->search($f)->count() > 9) ? true : false;
163     }
164     
165     /**
166      * @see Tinebase_Setup_DemoData_Abstract
167      * 
168      */
169     protected function _beforeCreate()
170     {
171         $this->_ccController  = Sales_Controller_CostCenter::getInstance();
172         $this->_taController  = Timetracker_Controller_Timeaccount::getInstance();
173         $this->_taController->sendNotifications(FALSE);
174         $this->_tsController  = Timetracker_Controller_Timesheet::getInstance();
175         $this->_tsController->sendNotifications(FALSE);
176         $this->_tsController->doContainerACLChecks(false);
177         
178         $this->_contractController    = Sales_Controller_Contract::getInstance();
179         $contracts = $this->_contractController->getAll();
180         $developmentString = self::$_de ? 'Entwicklung' : 'Development';
181         
182         $this->_contractsDevelopment = $contracts->filter('title', '/.' . $developmentString . '/', TRUE);
183         $this->_contractsMarketing = $contracts->filter('title', '/.Marketing/', TRUE);
184         
185         $this->_loadCostCentersAndDivisions();
186         
187         if (Tinebase_Application::getInstance()->isInstalled('HumanResources')) {
188             $this->_empController = HumanResources_Controller_Employee::getInstance();
189             $filter = new HumanResources_Model_EmployeeFilter(array());
190             $this->_employees = $this->_empController->search($filter);
191         }
192         
193         // set start date to start date of june 1st before last year
194         $date = Tinebase_DateTime::now();
195         $this->_startDate = $date->subMonth(3)->setTime(8,0,0);
196
197         // set clearedDate almost a month after
198         $this->_clearedDate = clone $this->_startDate;
199         $this->_clearedDate->addMonth(1)->subDay(2);
200     }
201     
202     /**
203      * creates shared tas
204      */
205     protected function _createSharedTimeaccounts()
206     {
207         // create 2 timeaccounts for each cc
208         $taNumber = 1;
209         
210         $userGroup = Tinebase_Group::getInstance()->getGroupByName('Users');
211         $developmentString = self::$_de ? 'Entwicklung' : 'Development';
212         if (! $userGroup) {
213             die('Could not find userGroup "Users", stopping.');
214         }
215         
216         $grants = array(array(
217             'account_id' => $userGroup->getId(),
218             'account_type' => 'group',
219             'bookOwnGrant' => TRUE,
220             'viewAllGrant' => TRUE,
221             'bookAllGrant' => TRUE,
222             // TODO: this shouldn't be neccessary, but is. why?:
223             'manageBillableGrant' => TRUE,
224             'exportGrant' => TRUE,
225             'adminGrant' => TRUE
226         ));
227         
228         $contractsIndex = 0;
229         
230         foreach($this->_costCenters as $costcenter) {
231             
232             $this->_timeAccounts[$costcenter->getId()] = new Tinebase_Record_RecordSet('Timetracker_Model_Timeaccount');
233             $i=0;
234             
235             while ($i < 2) {
236                 $i++;
237                 
238                 $ta = new Timetracker_Model_Timeaccount(array(
239                     'number'      => $taNumber,
240                     'title'       => Tinebase_Record_Abstract::generateUID(3),
241                     'grants'      => $grants,
242                     'status'      => 'billed',
243                     'cleared_at'  => $this->_clearedDate,
244                     'budget'      => NULL,
245                     'description' => 'Created By Tine 2.0 DEMO DATA'
246                 ));
247                 
248                 if (($costcenter->remark == 'Marketing') || ($costcenter->remark == $developmentString)) {
249                     $contract = $costcenter->remark == 'Marketing' ? $this->_contractsMarketing->getByIndex(rand(0, ($this->_contractsMarketing->count() -1))) : $this->_contractsDevelopment->getByIndex(rand(0, ($this->_contractsDevelopment->count() -1)));
250                     
251                     $ta->budget = $costcenter->remark == 'Marketing' ? 100 : NULL;
252                     $ta->relations = array(
253                         array(
254                             'own_model'              => 'Timetracker_Model_Timeaccount',
255                             'own_backend'            => 'SQL',
256                             'own_id'                 => NULL,
257                             'own_degree'             => Tinebase_Model_Relation::DEGREE_SIBLING,
258                             'related_model'          => 'Sales_Model_CostCenter',
259                             'related_backend'        => Tasks_Backend_Factory::SQL,
260                             'related_id'             => $costcenter->getId(),
261                             'type'                   => 'COST_CENTER'
262                         ),
263                         array(
264                             'own_model'              => 'Timetracker_Model_Timeaccount',
265                             'own_backend'            => 'SQL',
266                             'own_id'                 => NULL,
267                             'own_degree'             => Tinebase_Model_Relation::DEGREE_SIBLING,
268                             'related_model'          => 'Sales_Model_Contract',
269                             'related_backend'        => Tasks_Backend_Factory::SQL,
270                             'related_id'             => $contract->getId(),
271                             'type'                   => 'TIME_ACCOUNT'
272                         ));
273                     $ta->title = (self::$_de ? 'Zeitkonto mit ' : 'Timeaccount for ') . $contract->getTitle();
274                 } else {
275                     $ta->title = (self::$_de ? 'Zeitkonto mit KST ' : 'Timeaccount for CC ') . $costcenter->getTitle();
276                     $ta->relations = array(
277                         array(
278                             'own_model'              => 'Timetracker_Model_Timeaccount',
279                             'own_backend'            => 'SQL',
280                             'own_id'                 => NULL,
281                             'own_degree'             => Tinebase_Model_Relation::DEGREE_SIBLING,
282                             'related_model'          => 'Sales_Model_CostCenter',
283                             'related_backend'        => Tasks_Backend_Factory::SQL,
284                             'related_id'             => $costcenter->getId(),
285                             'type'                   => 'COST_CENTER'
286                         )
287                     );
288                 }
289                 
290                 $this->_timeAccounts[$costcenter->getId()]->addRecord($this->_taController->create($ta));
291                 
292                 $taNumber++;
293             }
294         }
295     }
296     
297     /**
298      * creates and persists a timesheet
299      * 
300      * @param array $data
301      * @return Tinebase_Record_Interface
302      */
303     protected function _createTimesheet($data)
304     {
305         $ts = new Timetracker_Model_Timesheet($data);
306         return $this->_tsController->create($ts);
307     }
308     
309     /**
310      * returns the cost center for the current account
311      */
312     protected function _getCurrentUsersCostCenter()
313     {
314         $employee = $this->_getCurrentUsersEmployee();
315         $salesCC =  HumanResources_Controller_CostCenter::getInstance()->getValidCostCenter($employee->getId(), NULL, TRUE);
316         return $salesCC;
317     }
318     
319     /**
320      * returns the employee for the current account
321      */
322     protected function _getCurrentUsersEmployee()
323     {
324         return $this->_employees->filter('account_id', Tinebase_Core::getUser()->accountId)->getFirstRecord();
325     }
326     
327     /**
328      * creates timesheets
329      */
330     protected function _createTimesheets()
331     {
332         if (Tinebase_Application::getInstance()->isInstalled('HumanResources')) {
333             $cc = $this->_getCurrentUsersCostCenter();
334         } else {
335             $cc = $this->_costCenters->filter('remark', 'Management')->getFirstRecord();
336         }
337         
338         
339         $ownTimeAccountRecordSet = $this->_timeAccounts[$cc->getId()]->sort('number');
340         $userId = Tinebase_Core::getUser()->accountId;
341         
342         $startDate = clone $this->_startDate;
343         $endDate   = clone $startDate;
344         $endDate->addMonth(3);
345         
346         $mkccId = $this->_marketingCostCenter->getId();
347         $deccId = $this->_developmentCostCenter->getId();
348         
349         $allMkccTimeAccountRecordSet = $this->_timeAccounts[$mkccId]->sort('number');
350         $allDeccTimeAccountRecordSet = $this->_timeAccounts[$deccId]->sort('number');
351         
352         $afterCleared = FALSE;
353         $stopIndex = 8;
354         
355         while ($startDate < $endDate) {
356             $wd = (int) $startDate->format('w');
357             
358             // create timesheets from tue -> fri, always a timeaccount of the users costcenter
359             if (($wd < 6) && ($wd > 2)) {
360                 // 8 hrs
361                 $ta = $ownTimeAccountRecordSet->getByIndex(rand(0, ($ownTimeAccountRecordSet->count() - 1)));
362                 $ts = $this->_createTimesheet(array(
363                     'account_id'     => $userId,
364                     'timeaccount_id' => $ta->getId(),
365                     'is_billable'    => false,
366                     'start_date'     => $startDate,
367                     'duration'       => 480,
368                     'description'    => static::$_de ? 'DemoData eigenes Zeitkonto' : 'DemoData own timeaccount',
369                     'is_cleared'     => (($ta->status == 'billed') ? true : false),
370                  ));
371             } else {
372                 
373                 // create timesheets on monday and tuesday
374                 $ta = $allMkccTimeAccountRecordSet->getByIndex(rand(0, ($allMkccTimeAccountRecordSet->count() - 1)));
375                 // 4 hrs for a marketing costcenter timeaccount
376                 $ts = $this->_createTimesheet(array(
377                     'account_id'     => $userId,
378                     'timeaccount_id' => $ta->getId(),
379                     'is_billable'    => false,
380                     'start_date'     => $startDate,
381                     'duration'       => 240,
382                     'description'    => static::$_de ? ('DemoData auf KST ' . $cc->number) : ('DemoData on costcenter ' . $cc->number),
383                     'is_cleared'     => (($ta->status == 'billed') ? true : false),
384                 ));
385                 
386                 $sd = clone $startDate;
387                 $sd->addMinute(300);
388                 $ta = $allDeccTimeAccountRecordSet->getByIndex(rand(0, ($allDeccTimeAccountRecordSet->count() - 1)));
389                 
390                 // 4 hrs for a development costcenter timeaccount
391                 $ts = $this->_createTimesheet(array(
392                     'account_id'     => $userId,
393                     'timeaccount_id' => $ta->getId(),
394                     'is_billable'    => false,
395                     'start_date'     => $sd,
396                     'duration'       => 240,
397                     'description'    => static::$_de ? ('DemoData auf KST ' . $cc->number) : ('DemoData on costcenter ' . $cc->number),
398                     'is_cleared'     => (($ta->status == 'billed') ? true : false),
399                 ));
400             }
401         
402             $startDate->addDay(1);
403         }
404     }
405     
406     /**
407      * @see parent
408      */
409     protected function _createTimesheetsForPwulf()
410     {
411         $this->_createTimesheets();
412     }
413
414     /**
415      * @see parent
416      */
417     protected function _createTimesheetsForRwright()
418     {
419         $this->_createTimesheets();
420     }
421
422     /**
423      * @see parent
424      */
425     protected function _createTimesheetsForSclever()
426     {
427         $this->_createTimesheets();
428     }
429     
430     /**
431      * @see parent
432      */
433     protected function _createTimesheetsForJmcblack()
434     {
435         $this->_createTimesheets();
436     }
437     
438     /**
439      * @see parent
440      */
441     protected function _createTimesheetsForJsmith()
442     {
443         $this->_createTimesheets();
444     }
445 }