Fix #7123 - getting abra ready to test
[Pman.Xtuple] / ApplyGLFinal.php
1 <?php
2 require_once 'Pman.php';
3
4
5
6 // this will produce an excel spreadsheet with the list of adjustments to do..
7
8 class Pman_Xtuple_ApplyGLFinal extends Pman
9 {
10     
11     static $cli_desc = "Migrate Netsuite -- apply final GL balances";
12     
13     function getAuth()
14     {
15         $au = $this->getAuthUser();
16         
17         if (!empty($au->id)) {
18             return true;
19         }
20         if (!HTML_FlexyFramework::get()->cli) {
21             die("invalid url");
22         }
23         
24     }
25     var $db = false;
26     var $year=  2009;
27     
28     function yfile()
29     {
30         switch($this->db) {
31             case 'hk':
32                 return   $this->rootDir  . '/../netsuite_balances/netsuite-HK-apr'. $this->year . '.csv';
33             case 'sg':
34                 return   $this->rootDir  . '/../netsuite_balances/netsuite-SG-sep'. $this->year . '.csv';
35             default:
36                 die("OPPS NO DB?");
37         }
38         
39     }
40     
41     
42     function get()
43     {
44        $this->jerr("disabled");
45        
46         $this->db = preg_match('/hk$/', $this->bootLoader->database) ? 'hk' : 'sg';
47         
48         $acc = array();
49         $head = array('accnt_number', 'accnt_name', 'curr', 'accnt_type');
50         $yo = array();
51         for ($y = 2009; $y < 2013; $y++) {
52             $yo[$y] = count($head);
53             array_push($head , 'CUR', 'NS' .$y, 'XT' .$y, 'DIFF'.  $y, '' );
54             
55             $res = $this->process($y);
56             foreach($res as $row) {
57                 if (!isset($acc[$row['id']])) {
58                     $acc[$row['id']] = array();
59                 }
60                 $acc[$row['id']][$y] = $row;
61             }
62             
63             
64         }
65         
66         uasort($acc, function($ll,$vv) {
67            // // sort by accnt type first.
68             $l = array_pop(array_values($ll));
69             $v = array_pop(array_values($vv));
70             //echo '<PRE>';print_R($l);exit;
71             if ($l['accnt_type'] != $v['accnt_type']) {
72                 return $l['accnt_type']  > $v['accnt_type'] ? 1 : -1;
73             }
74             if ($l['accnt_subaccnttype_code'] != $v['accnt_subaccnttype_code']) {
75                 return $l['accnt_subaccnttype_code']  > $v['accnt_subaccnttype_code'] ? 1 : -1;
76             }
77             
78             return $l['accnt_descrip']  > $v['accnt_descrip'] ? 1 : -1;
79             
80         });
81         
82         
83         // need to sort accounts...
84         // need to feetch all totals here, rather than later...
85         // but need to know which currencies to fetch...
86         
87         //echo '<PRE>';
88         //print_r($head);exit;
89         $rows = array();
90         foreach($acc as $id => $years ) {
91             $first = array_pop(array_values($years));
92             //print_r($first);
93             $row = array_fill(0, 30, '');
94             $row[0] = $first['accnt_number'];
95             $row[1] = $first['accnt_descrip'];
96             $row[2] = $first['curr'];
97             $row[3] = $first['accnt_type'] . '/' . $first['accnt_subaccnttype_code'];
98             
99             
100             //print_r($years);
101             
102             for ($y = 2009; $y < 2013; $y++) {
103                 $o = $yo[$y];
104                 if (!isset($years[$y])) {
105                     continue;
106                 }
107                 $rec = $years[$y];
108                 
109                 if (empty($rec['accnt_number'])) {
110                     
111                     $curs = array_keys($rec['ns']) ;
112                     if (count($curs) != 1) {
113                         print_r($rec);
114                         die("got a ns only acc. with multiple tx's in");
115                     }
116                     $cur = $curs[0];
117                     $row[$o] = $cur ;
118                     $row[$o+1] =  $rec['ns'][$cur]['fc'];
119                     $row[$o+2] = 0;
120                     $row[$o+3] = '?? ' . $rec['ns'][$cur]['fc']; //<<< probaly not!
121                     continue;
122                     
123                 }
124                 
125                 
126                 if (empty($rec['ns'])) {
127                     $row[$o] = $rec['base'];
128                     $row[$o+1] = 0;
129                     $row[$o+2] =  sprintf('%0.2f',$rec['XT.' . $rec['base']  ]);
130                     $row[$o+3] = -1.0 * $rec['XT.' .$rec['base']  ];
131                     continue;
132                     
133                 }
134                 
135                 if (!isset($rec['ns.' .$rec['diffcur']  ])) {
136                     echo "diffcurr NS not available...";
137                     print_R($rec);
138                     exit;
139                 }
140                 
141                 
142                 
143                 $row[$o] = $rec['diffcur'];
144                 $row[$o+1] =  sprintf('%0.2f',$rec['ns.' . $rec['diffcur']  ]);
145                 $row[$o+2] =  sprintf('%0.2f',$rec['XT.' .$rec['diffcur']  ]);
146                 $row[$o+3] =  sprintf('%0.2f', -1.0 * $rec['diff'] );
147             }
148             $rows[] = $row;
149             
150         }
151         
152         
153         // output csv..
154         
155         header('Content-type: text/csv');
156         header( 'Content-Disposition: attachment;filename=Accounts.csv');
157         $fh = fopen('php://output','w');
158         fputcsv($fh, $head);
159         $lac = '';
160         foreach($rows as $o) {
161             $ac = $o[3];
162             if (!empty($lac) && $lac !=$ac) {
163                 fputcsv($fh, array());
164             }
165             $lac = $ac;
166             fputcsv($fh, $o);
167         }
168         fclose($fh);
169         exit;
170         
171         
172         
173         
174         
175         
176         
177         
178         
179         
180         
181         exit;
182         
183     }
184     
185     
186     function process($y)
187     {
188         //print_r($this);exit;
189         $this->year = $y;
190         
191         
192         $base = $this->yfile();
193         
194         
195          
196         
197         $fh = fopen($base,'r');
198         if (!$fh) {
199             die("no file");
200         }
201         
202         
203         
204         $lines = array();
205         $accnts = array();
206         $start = false;
207         while (false !== ($row = fgetcsv($fh))) {
208             
209             if (!$start) {
210                 //var_dump($row);
211                 if (trim($row[0]) == 'Name') {
212                     $start = true;
213                     continue;
214                 }
215                 continue;
216             }
217             
218              if (str_replace(',','', $row[3]) * 1.0 == 0.0) {
219                 continue;
220              }
221             
222             $acc = trim($row[0]);
223             if (!isset($lines[$acc])) {
224                 $lines[$acc] = $this->acctDef($acc);
225                 if ($lines[$acc]['id']) {
226                     $accnts[] = $lines[$acc]['id'];
227                 }
228                 $lines[$acc]['ns.name'] = $acc;
229                 
230             }
231             
232             $curr = trim($row[2]);
233             if ($curr == 'CNY') {
234                 $curr = 'RMB';
235             }
236             
237             
238             $hkd = str_replace(',', '', preg_replace('/HK\$/', '', $row[1]));
239             $fc = str_replace(',','', $row[3]);
240             
241             if (
242                     ($hkd > 0 && $fc < 0)
243                 ||
244                     ($hkd < 0 && $fc > 0)
245                )
246             {
247                 $fc *= -1;
248             }
249              
250             
251             $lines[$acc]['ns'][$curr] = array(
252                     'fc' => $fc,
253                     'HKD' => $hkd
254             );
255         }
256         fclose($fh);
257         
258         //DB_DataObject::DebugLevel(1);
259         // now fill in the xtuple data..
260         $gl = DB_DataObject::Factory('gltrans');
261         
262         $dt = $this->db == 'hk' ? ($this->year .'-04-30') : ($this->year .'-09-30');
263         $dt = $dt== '2012-09-30' ? '2012-08-31' : $dt;
264         
265         
266         $gl->selectAdd();
267         $gl->selectAdd('distinct(gltrans_accnt_id ) as gltrans_accnt_id ');
268         $gl->whereAdd('gltrans_accnt_id NOT IN (' .implode(',', $accnts) .')');
269         $gl->whereAdd("gltrans_date < '{$dt}'::date + INTERVAL '1 DAY'");
270         $other = $gl->fetchAll('gltrans_accnt_id');
271          
272         foreach($other as $ac) {
273             $lines['XT.'.$ac] = $this->acctDef($ac, true);
274         }
275         $res = array();
276         
277         // at this point we should decide which currency to use for the whole account.
278         
279         
280         
281         
282         //print_r($lines);
283         foreach($lines as $k=> $line) {
284             $add = $this->study($line);
285             
286              
287             
288             if ($add) {
289                 $res[$k] = $add;
290             }
291         }
292         return $res;
293     }
294     
295     function acctDef($name, $isnum=false) {
296         
297         $d = DB_DataObject::Factory('accnt');
298         $d->autoJoin();
299         //why?
300         if (!$isnum) {
301             if ($name == 'Bank - HKD Transfer Account (HK HQ)') {
302                 $name = 'Bank - HKD transfer Account (HK HQ)';
303             }
304             if ($name == 'CCB Motor Hire Purchase (HK HQ)') {
305                 $name = 'Hire Purchase of Motor vehicle (HK HQ)';
306             }
307             if ($name == 'Loss on disposal') {
308                 $name = 'Loss on disposal of assets';
309             }
310             $d->accnt_descrip = $name;
311             
312             //DB_DataObject::debugLevel(1);
313             
314             
315             $d->whereAdd('accnt_number::integer < 1000');
316             if ($d->count() != 1) {
317                 //echo "Can not find accnt $name\n";
318                 
319                 if (in_array($name , array(
320                     'Freight Income (HK HQ)' // known badd..
321     
322                     
323                 ))) {
324                     return array(
325                        'id' => 0,
326                        'accnt_descrip' => $name,
327                        'accnt_number' => '',
328                        'curr_id' => 1, // usd...
329                        'curr' => 'USD',
330                        'accnt_type' => '',
331                        'accnt_subaccnttype_code' => '',
332                        
333                    );   
334                 }
335                 
336                 exit;
337                 
338             }
339             $d->find(true);
340         } else {
341             $d->get($name);
342         }
343         $cur = 'HKD'; //$this->db == 'hk' ? 'HKD' : 'SGD';
344         $ret = array(
345                 'id' => $d->accnt_id,
346                 'curr' => $d->accnt_curr_id_curr_name,
347                 'curr_id' => $d->accnt_curr_id,
348                 'accnt_type' => $d->accnt_type,
349                 'accnt_number' => $d->accnt_number,
350                 'accnt_descrip' => $d->accnt_descrip,
351                 'accnt_subaccnttype_code' => $d->accnt_subaccnttype_code,
352                 'base' => $cur,
353                 'ns' => array()
354         );
355         
356         // find the total in local...
357         
358         
359         $ret['XT.'. $cur] = $this->getAccntAt($d->accnt_id, $cur);
360         
361         if ($cur != $ret['curr']) {
362             $ret['XT.'. $ret['curr']] = $this->getAccntAt($d->accnt_id, $ret['curr_id']);
363         }
364         
365         
366         
367         return $ret;
368         
369     }
370      
371     function getAccntAt($id, $curr=false) {
372         //DB_DataObject::debugLevel(1);
373         // STATEMENT : Q, L, A
374         $dt = $this->db == 'hk' ? ($this->year .'-04-30') : ($this->year .'-09-30');
375         $dt = $dt== '2012-09-30' ? '2012-08-31' : $dt;
376         // the last column is only advisory, we can not base any data on it..
377         //if ($dt == '2012-09-30') {
378         //    $dt  = '2012-08-30';
379         //}
380         
381         
382         static $pds = array();
383         
384         if (!isset($pds[$dt])) {
385             $p = DB_DAtaObject::Factory('period');
386             $p->get('period_end', $dt);
387
388             $pds[$dt] = $p->pid();
389         }
390         
391         $pid = $pds[$dt];
392         
393           
394         
395         
396         $gl = DB_DataObject::Factory('trialbal');
397         
398         
399         $gl->selectAdd();
400         
401         if (!$curr) {
402             $gl->selectAdd('trialbal_ending');
403         } else {
404             if (!is_numeric($curr)) {
405                 $curr = "getcurrid('$curr')";
406                 
407                 
408             }
409             $gl->selectAdd("
410                     currtocurr(
411                         baseCurrId(),
412                         $curr ,
413                         trialbal_ending,
414                         '$dt'
415                         
416                     ) as trialbal_ending ");
417             
418             
419         }
420         
421         $gl->trialbal_accnt_id = $id;
422         $gl->trialbal_period_id = $pid;
423         $gg = clone ($gl);
424         if (!$gl->find(true)) {
425             DB_DataObject::debugLevel(1);
426             $gg->find(true);
427             exit;
428         }
429         return   isset($gl->trialbal_ending)  ? $gl->trialbal_ending : 0.0;
430             
431         
432         
433     }
434     
435     function study($line) {
436         
437         // comparison = should be done on base currency for everything except the banks..
438         
439         //print_r($line);exit;
440         
441         $compare = 'HKD'; //$this->db == 'HK' ? 'HKD' : 'SGD';
442         if ($line['accnt_subaccnttype_code'] == 'CA') {
443             // it's a bank
444             $compare = $line['curr'];
445         }
446         
447         //print_r($line);exit;
448         if (empty($line['ns']) && $line['XT.'.$line['base']] == 0.0) {
449             return false;
450         }
451         
452         if (empty($line['ns']) || empty($line['id'])) {
453             //echo "SKIP {$line['accnt_descrip']}\n";
454             return $line;
455         }
456         if (!isset($line['accnt_type'])) {
457             print_r($line);exit;
458         }
459         
460         //if ($this->db == 'hk') {
461         $hkd = 0.0;
462         foreach($line['ns'] as $cur=>$data) {
463             $hkd += $data['HKD'];
464         }
465         $line['ns.HKD'] = $hkd;
466         $base = 'HKD';
467             
468         //if ($this->db == 'sg') {
469         //    $sgd = 0.0;
470         //    foreach($line['ns'] as $cur=>$data) {
471         //        $sgd += $data['HKD'] / 6.2;
472         //    }
473         //    $line['ns.SGD'] = $sgd;
474         //    $base = 'SGD';
475         //}
476         
477         $fac = 1;
478         switch($line['accnt_type'] ) {
479             case 'A':
480             case 'E':
481             case 'R':
482             case 'L':
483                 $fac = -1.0;
484                 break;
485             default:
486                 $fac = 1.0;
487                 break;
488                 
489         }
490          
491         if (count(array_keys($line['ns'])) == 1) {
492             // then it should be a simple match
493             
494             
495             if (isset($line['ns'][ $compare   ])) {
496                 // use the base currency to compare..
497                 $line['ns.' . $compare] = $line['ns'][  $compare  ]['fc'];
498                 $line['diffcur'] = $compare;
499                 if ($line['XT.' .$compare ] == ($fac * $line['ns'][  $compare  ]['fc'])) {
500                         // they match!!
501                         $line['diff'] = '';
502                         return $line;
503                 }
504                 $line['diff'] = sprintf('%0.2f',
505                         $line['XT.' .$compare ] - ($fac * $line['ns'][  $compare ]['fc']));
506                 
507                 return $line; 
508                 
509             }
510             
511             // otherise try and use base currency.
512             
513             if ($this->db == 'sg') {
514                 if (!isset($line['ns.' . $line['base'] ] )) {
515                     //echo '<PRE>';print_R($line);exit;
516                     $line['ns.' . $line['base'] ] = sprintf('%0.2f', $line['ns'][  'HKD' ]['fc'] * (1/6.2));
517                 }
518             } else {
519             // use the base currency to compare..
520                 $line['ns.' . $line['base'] ] = sprintf('%0.2f', $line['ns'][  $line['base']   ]['fc']);
521             }
522             $line['diffcur'] = $line['base'];
523             if ($line['XT.' .$line['base'] ] == ($fac * $line['ns.' . $line['base'] ])) {
524                     // they match!!
525                     $line['diff'] = '';
526                     return $line;
527             }
528             $line['diff'] = sprintf('%0.2f', $line['XT.' .$line['base'] ] - ($fac * $line['ns.' . $line['base'] ]));
529             
530             return $line; 
531               
532             //print_R($line);exit;
533             
534             
535         }
536         // otherwise we have to compare on base currency...
537         
538         if (!isset($line['XT.' . $base])) {
539             echo "MISSING: XT." . $base;
540             print_r($line);exit;
541         }
542         // got a multicurrency netsuite..
543         //if ($line['XT.HKD'] == ($fac * $hkd)) {
544             // they match!!
545         //    return false;
546         //}
547         $line['diff'] = sprintf('%0.2f', $line['XT.' . $base] - ($fac * $line['ns.'.$base]));
548         $line['diffcur'] = $base;
549         return $line; 
550         
551         
552         
553         
554     }
555     
556 }