DataObjects/Period.php
[Pman.Xtuple] / DataObjects / Period.php
1 <?php
2 /**
3  * Table Definition for period
4  */
5 require_once 'DB/DataObject.php';
6
7 class Pman_Xtuple_DataObjects_Period extends DB_DataObject 
8 {
9     ###START_AUTOCODE
10     /* the code below is auto generated do not remove the above tag */
11
12     public $__table = 'period';              // table name
13     public $period_id;                       // int4(4)  not_null default_nextval%28period_period_id_seq%29 primary_key
14     public $period_start;                    // date(4)  
15     public $period_end;                      // date(4)  
16     public $period_closed;                   // bool(1)  
17     public $period_freeze;                   // bool(1)  
18     public $period_initial;                  // bool(1)  default_false
19     public $period_name;                     // text(-1)  
20     public $period_yearperiod_id;            // int4(4)  
21     public $period_quarter;                  // int4(4)  
22     public $period_number;                   // int4(4)  not_null
23
24     
25     /* the code above is auto generated do not remove the tag below */
26     ###END_AUTOCODE
27     
28     
29     function yearperiod()
30     {
31         $d = DB_DataObject::Factory('yearperiod');
32         $d->get($this->period_yearperiod_id);
33         return $d;
34     }
35     
36     function applyFilters($q, $au, $roo)
37     {
38         if (!empty($q['_initPeriods'])) {
39             $this->initPeriods($roo);
40             $roo->jok("DONE");
41         }
42         if (!empty($q['_renamePeriods'])) {
43             $this->renamePeriods($roo);
44             $roo->jok("DONE");
45         }
46         if(!empty($q['_with_transactions'])){
47             $this->selectAdd("
48                 (
49                     SELECT 
50                             COUNT(gltrans_id)
51                     FROM
52                             gltrans
53                     WHERE
54                             (gltrans_date BETWEEN period_start AND period_end)
55                             AND
56                             (NOT gltrans_deleted)
57                             AND
58                             gltrans_posted
59                 ) AS transactions
60             ");
61         }
62         if(!empty($q['_status'])){
63             switch ($q['_status']){
64                 case 'O' :
65                     $this->period_closed = FALSE;
66                     break;
67                 case 'C' :
68                     $this->period_closed = TRUE;
69                     break;
70                 default :
71                     break;
72             }
73         }
74         
75         
76     }
77     
78     function initDatabase($roo)
79     {
80        
81          
82         if ($this->count()) {
83             echo "SKIP - already have periods\n";
84             return;
85         }
86         $p->initPeriods($roo);
87         
88     }
89     
90     
91     function initPeriods($roo)
92     {
93         
94         // should be configurable somewhere...
95         $db = substr($this->database(),-2);
96         switch($db) {
97             case 'au':
98                 $start = '2006';
99                 //HK: 1 May - 30 Apr
100                 //SG: 1 Oct - 30 Sept
101                 $sdate = '-07-01';
102                 $edate = '-06-30';
103                 break;
104             
105             case 'hk':
106             case 'cn':
107             case 'zh':
108             case 'my':
109                 
110                 $start = date('Y') -1;//
111                 //HK: 1 May - 30 Apr
112                 //SG: 1 Oct - 30 Sept
113                 $sdate = '-05-01';
114                 $edate = '-04-30';
115                 
116                 break;
117             default:
118                 $roo->jerr("not set up yet");
119         }
120         
121         
122         
123         $yp = DB_DataObject::factory('yearperiod');
124         
125         //DB_DataObject::debugLevel(1);
126         
127         for ($i = $start; $i < date('Y')+10 ;$i++ ) {
128             
129             
130              
131             // we should now have the period + id..
132             
133             for ($m=0; $m < 12; $m++) {
134                 $ms = !$m ? ($i . $sdate) : date('Y-m-01', strtotime( $i . $sdate . ' + ' . $m . ' MONTHS' ));
135                 $me = date('Y-m-d',strtotime( $ms .' + 1 MONTHS - 1 DAYS'));
136                 
137                 $p = DB_DataObject::factory('period');
138                 $p->get('period_start', $ms);
139                      
140                 $yp = $this->createYearPeriod($i, $sdate, $edate);
141                 
142                 $p->get('period_start', $ms);
143                 
144                 if ($p->period_closed || $p->period_freeze) {
145                     continue;
146                 }
147                 $end = date('Y-m-d',strtotime( "$ms + 1 MONTH - 1 DAY"));
148                 
149                 $p->setFrom(array(
150                     'period_closed' => false,
151                     'period_freeze' => false,
152                     'period_end' => $end,
153                     //'period_initial       | t
154                     'period_name'          =>  date('Y-m', strtotime($ms)) .' '. date('M', strtotime($ms)),
155                     'period_yearperiod_id'  => $yp->yearperiod_id,
156                     'period_quarter'   => floor($m/3) + 1,
157                     'period_number'  => $m + 1
158                 ));
159                 $p->period_id ? $p->update() : $p->insert();
160                 
161             }
162           
163             
164             
165         }
166           
167         
168     }
169     function createYearPeriod($i, $sdate, $edate)
170     {   
171         $yp = DB_DataObject::factory('yearperiod');
172         if ( $yp->get('yearperiod_start', $i.$sdate)) {
173             return $yp;
174         }
175         $yp = DB_DataObject::factory('yearperiod');
176         $ni = $i+1;
177         $yp->whereAdd("yearperiod_start >= '{$i}-01-01' AND yearperiod_start < '{$ni}-01-01'");
178         $yp->limit(1);
179         $yp->find(true);
180         
181         $yp->setFrom(array(
182             'yearperiod_start' => $i . $sdate,
183             'yearperiod_end' => ($i+1) . $edate,
184             'yearperiod_closed' => false,
185         ));
186         if (!empty($yp->yearperiod_id)) {
187             $yp->update();
188         } else { 
189             $yp->insert();
190         }
191         return $yp;
192     }
193     
194     function renamePeriods()
195     {
196         $p = DB_DataObject::factory($this->tableName());
197         //$p->whereAdd("period_name not like  '____-__ %'");
198         $all = $p->fetchAll();
199         foreach($all as $p) {
200             $pp = clone($p);
201             
202             $yp = $p->yearperiod();
203             $fy = date('Y', strtotime($yp->yearperiod_start));
204             $fe = date('Y', strtotime($yp->yearperiod_end));
205             $fy_name = "(FY {$fy} - {$fe})";
206             
207             $ms = $p->period_start;
208             
209             $p->period_name = date('Y-m', strtotime($ms)) .' '. date('M', strtotime($ms)) . ' ' . $fy_name ;
210             $p->update($pp);
211         }
212         
213     }
214     
215     function isClosed($date)
216     {
217         $date = date('Y-m-d',strtotime($date));
218         $p = DB_DataObject::Factory('period');
219         $p->whereAdd("'{$date}' BETWEEN period_start AND period_end");
220         $p->find(true);
221         return ($p->period_closed || $p->period_freeze ) ? true : false;
222         
223     }
224     
225     function firstOpen()
226     {
227         $p = DB_DataObject::Factory('period');
228         $p->orderBy('period_start ASC');
229         $p->limit(1);
230         $p->period_closed = 0;
231         $p->period_freeze = 0;
232         $p->find(true);
233         return $p;
234     }
235     
236     function createPeriod($y)
237     {
238         
239         var_dump($y);
240         $db = substr($this->database(),-2);
241         switch($db) {
242             case 'au':
243                 $sdate = '-07-01';
244                 $edate = '-06-30';
245                 break;
246             
247             case 'hk':
248             case 'cn':
249             case 'my':
250                 
251                 $sdate = '-05-01';
252                 $edate = '-04-30';
253                 break;
254             default:
255                 HTML_FlexyFramework::get()->page->jerr("not set up yet");
256         }
257         
258         $yp = $this->createYearPeriod($y, $sdate, $edate);
259         
260         for ($m=0; $m < 12; $m++) {
261             $ms = !$m ? ($y . $sdate) : date('Y-m-01', strtotime( $y . $sdate . ' + ' . $m . ' MONTHS' )); // period_start
262             $me = date('Y-m-d',strtotime( $ms .' + 1 MONTHS - 1 DAYS')); // period_end
263             
264             $p = DB_DataObject::factory('period');
265             $p->get('period_start', $ms);
266
267             if ($p->period_closed || $p->period_freeze) {
268                 continue;
269             }
270             
271             $p->setFrom(array(
272                 'period_closed' => false,
273                 'period_freeze' => false,
274                 'period_start' => $ms,
275                 'period_end' => $me,
276                 'period_name'          =>  date('Y', strtotime($ms)) .' '. date('M', strtotime($ms)),
277                 'period_yearperiod_id'  => $yp->yearperiod_id,
278                 'period_quarter'   => floor($m/3) + 1,
279                 'period_number'  => $m + 1
280             ));
281             $p->period_id ? $p->update() : $p->insert();
282
283         }
284         
285         
286     }
287     
288     function beforeInsert($q,$roo)
289     {
290         if(isset($q['_group'])){
291             $roo->jerr("not supported");
292             
293             $list = json_decode($q['_group'], true);
294             foreach ($list as $l){
295                 $period = DB_DataObject::factory('period');
296                 if(!$period->get($l['period_id'])){
297                     $roo->jerr("Can not found the period id : {$l['period_id']}");
298                 }
299                 $period->close($roo);
300             }
301             $roo->jok("CLOSED");
302         }
303         
304         if(isset($q['_addExtraYear'])){
305             $yearperiod = DB_DataObject::factory('yearperiod');
306             $yearperiod->selectAdd();
307             $yearperiod->selectAdd("
308                 (EXTRACT(year FROM MAX(yearperiod_end))) AS next_year
309             ");
310             if ($yearperiod->count()) {
311                 $yearperiod->find(true);
312                 $this->createPeriod($yearperiod->next_year);    
313             } else {
314                 $this->createPeriod(date('Y')-1);
315             }
316             
317             
318             $roo->jok("ADDED");
319         }
320     }
321     
322     function beforeUpdate($old, $q,$roo)
323     {
324         
325         $valid_actions = array('open','close','freeze','thaw');
326         
327         if(!empty($q['_action'])) {
328             if (!in_array($q['_action'], $valid_actions)) {
329                 $roo->jerr("invalid action");
330             }
331             
332             $method = $q['_action'];
333             
334             
335             $this->$method($roo);
336             
337             if(!empty($q['_second_action']) && in_array($q['_second_action'], $valid_actions)) {
338                 $method = $q['_second_action'];
339                 $this->$method($roo);
340             }
341             
342             
343             $roo->jok("oops");
344         }
345         
346     }
347     
348     /*
349      * open the period
350      */
351     function open($roo)
352     {
353         $period = DB_DataObject::factory('period');
354         $period->query("SELECT openAccountingPeriod({$this->period_id}) AS result");
355         $period->fetch();
356         if($period->result < 0){
357             switch ($period->result){
358                 case -1 :
359                     $roo->jerr("This period is already open! name : {$this->period_name} result : {$period->result}");
360                     break;
361                 case -2 :
362                     $roo->jerr("This period is frozen! name : {$this->period_name} result : {$period->result}");
363                     break;
364                 case -3 :
365                     $roo->jerr("Some period after this period have been closed! name : {$this->period_name} result : {$period->result}");
366                     break;
367                 case -4 :
368                     $roo->jerr("This yearperiod of this period has been closed! name : {$this->period_name} result : {$period->result}");
369                 default :
370                     $roo->jerr("Error occur on open accounting period! name : {$this->period_name} result : {$period->result}");
371                     break;
372             }
373         }
374     }
375     
376     /*
377      * close the period
378      */
379     function close($roo)
380     {
381        
382         
383         $period = DB_DataObject::factory('period');
384         $period->query("SELECT closeAccountingPeriod({$this->period_id}) AS result");
385         $period->fetch();
386         if($period->result < 0){
387             switch ($period->result){
388                 case -1 :
389                     $roo->jerr("This period is already close! name : {$this->period_name} result : {$period->result}");
390                     break;
391                 case -2 :
392                     $roo->jerr("The day before this period is not belongs to another period! name : {$this->period_name} result : {$period->result}");
393                     break;
394                 case -3 :
395                     $roo->jerr("Pervious period is not closed! name : {$this->period_name} result : {$period->result}");
396                     break;
397                 case -4 :
398                     $roo->jerr("Next period is not defined! name : {$this->period_name} result : {$period->result}");
399                     break;
400                 case -5 :
401                     $roo->jerr("Prematurely close this period! name : {$this->period_name} result : {$period->result}");
402                     break;
403                 case -6 : 
404                     $roo->jerr("Can not found the yearperiod of the next period! name : {$this->period_name} result : {$period->result}");
405                     break;
406                 default :
407                     $roo->jerr("Error occur on close accounting period! name : {$this->period_name} result : {$period->result}");
408                     break;
409             }
410         }
411        
412         return true;
413     }
414     
415     /*
416      * freeze the period
417      */
418     function freeze($roo)
419     {
420         $period = DB_DataObject::factory('period');
421         $period->query("SELECT freezeAccountingPeriod({$this->period_id}) AS result");
422         $period->fetch();
423         if($period->result < 0){
424             switch ($period->result){
425                 case -1 :
426                     $roo->jerr("This period is still open! name : {$this->period_name} result : {$period->result}");
427                     break;
428                 case -2 :
429                     $roo->jerr("This period is already frozen! name : {$this->period_name} result : {$period->result}");
430                     break;
431                 default :
432                     $roo->jerr("Error occur on close accounting period! name : {$this->period_name} result : {$period->result}");
433                     break;
434             }
435         }
436     }
437     
438     /*
439      * thaw the period
440      */
441     function thaw($roo)
442     {
443         $period = DB_DataObject::factory('period');
444         $period->query("SELECT thawAccountingPeriod({$this->period_id}) AS result");
445         $period->fetch();
446         if($period->result < 0){
447             switch ($period->result){
448                 case -2 :
449                     $roo->jerr("This period is not frozen! name : {$this->period_name} result : {$period->result}");
450                     break;
451                 default :
452                     $roo->jerr("Error occur on close accounting period! name : {$this->period_name} result : {$period->result}");
453                     break;
454             }
455         }
456     }
457 }