PageRenderTime 42ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/phreedom/classes/beg_balances_imp.php

http://phreedom.googlecode.com/
PHP | 315 lines | 274 code | 7 blank | 34 comment | 46 complexity | bdeb9f7c75fde90eb83d33516133eaa1 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0
  1. <?php
  2. // +-----------------------------------------------------------------+
  3. // | PhreeBooks Open Source ERP |
  4. // +-----------------------------------------------------------------+
  5. // | Copyright (c) 2008, 2009, 2010, 2011, 2012 PhreeSoft, LLC |
  6. // | http://www.PhreeSoft.com |
  7. // +-----------------------------------------------------------------+
  8. // | This program is free software: you can redistribute it and/or |
  9. // | modify it under the terms of the GNU General Public License as |
  10. // | published by the Free Software Foundation, either version 3 of |
  11. // | the License, or any later version. |
  12. // | |
  13. // | This program is distributed in the hope that it will be useful, |
  14. // | but WITHOUT ANY WARRANTY; without even the implied warranty of |
  15. // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
  16. // | GNU General Public License for more details. |
  17. // +-----------------------------------------------------------------+
  18. // Path: /modules/phreebooks/classes/beg_balances_imp.php
  19. //
  20. class beg_bal_import {
  21. function __construct() {
  22. }
  23. function processCSV($upload_name = '') {
  24. global $coa, $db, $currencies, $messageStack;
  25. if (!$this->cyberParse($upload_name)) return false; // parse the submitted string, check for csv errors
  26. //echo 'parsed string = '; print_r($this->records); echo '<br />';
  27. $row_id = 0;
  28. while ($row_id < count($this->records)) {
  29. $current_order = $this->records[$row_id];
  30. // pre-process and check for errors
  31. if (!in_array($current_order['gl_acct'], $coa) || !in_array($current_order['inv_gl_acct'], $coa)) {
  32. $messageStack->add(GL_BEG_BAL_ERROR_1 . ($row_id + 1), 'error');
  33. return false;
  34. }
  35. if (!$current_order['order_id']) {
  36. switch (JOURNAL_ID) {
  37. case 6:
  38. $messageStack->add(sprintf(GL_BEG_BAL_ERROR_2, ($row_id + 1)),'caution');
  39. $this->records[$row_id]['waiting'] = 1;
  40. break;
  41. default:
  42. $messageStack->add(GL_BEG_BAL_ERROR_3 . ($row_id + 1), 'error');
  43. return false;
  44. }
  45. }
  46. $this->records[$row_id]['post_date'] = gen_db_date($current_order['post_date']); // from mm/dd/yyyy to YYYY-MM-DD
  47. if (!validate_db_date($this->records[$row_id]['post_date'])) {
  48. $messageStack->add(sprintf(GL_BEG_BAL_ERROR_4, ($row_id + 1)) . DATE_FORMAT, 'error');
  49. return false;
  50. }
  51. switch (JOURNAL_ID) { // total amount is calculated for PO/SOs
  52. case 6:
  53. case 12:
  54. $this->records[$row_id]['total_amount'] = $currencies->clean_value($current_order['total_amount']);
  55. if ($current_order['total_amount'] == 0) {
  56. $messageStack->add(GL_BEG_BAL_ERROR_5 . ($row_id + 1),'caution');
  57. $this->records[$row_id]['skip_this_record'] = 1;
  58. }
  59. default:
  60. }
  61. // TBD check for duplicate so/po/invoice numbers
  62. $row_id++;
  63. }
  64. if (is_array($this->records)) {
  65. // *************** START TRANSACTION *************************
  66. $db->transStart();
  67. if (!$this->submitJournalEntry()) {
  68. $db->transRollback();
  69. if (DEBUG) $messageStack->write_debug();
  70. return false;
  71. }
  72. $db->transCommit(); // post the chart of account values
  73. if (DEBUG) $messageStack->write_debug();
  74. // *************** END TRANSACTION *************************
  75. }
  76. return true;
  77. }
  78. function cyberParse($upload_name) {
  79. $lines = file($_FILES[$upload_name]['tmp_name']);
  80. if(!$lines) return false;
  81. $title_line = trim(array_shift($lines)); // pull header and remove extra white space characters
  82. $titles = explode(",", str_replace('"', '', $title_line));
  83. $records = array();
  84. foreach ($lines as $line_num => $line) {
  85. $parsed_array = $this->csv_string_to_array(trim($line));
  86. $fields = array();
  87. for ($field_num = 0; $field_num < count($titles); $field_num++) {
  88. $fields[$titles[$field_num]] = $parsed_array[$field_num];
  89. }
  90. $records[] = $fields;
  91. }
  92. $this->records = $records;
  93. return true;
  94. }
  95. function csv_string_to_array($str) {
  96. $results = preg_split("/,(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))/", trim($str));
  97. return preg_replace("/^\"(.*)\"$/", "$1", $results);
  98. }
  99. function submitJournalEntry() {
  100. global $db, $currencies, $messageStack;
  101. $entry_count = 0;
  102. $row_cnt = 0;
  103. while($row_cnt < count($this->records)) {
  104. $order = $this->records[$row_cnt];
  105. $glEntry = new journal();
  106. // determine if date is within a known period, if date is before period 1 use period = 0 (and enter beginning balances)
  107. $glEntry->period = gen_calculate_period($order['post_date'], $hide_error = true); // date format YYYY-MM-DD
  108. if (!$glEntry->period) $glEntry->period = 1; // if out of range default to first period (required to be valid period or it won't post)
  109. // build journal main entry
  110. $glEntry->journal_id = JOURNAL_ID;
  111. $glEntry->post_date = $order['post_date'];
  112. $glEntry->description = sprintf(TEXT_JID_ENTRY, constant('ORD_TEXT_' . JOURNAL_ID . '_WINDOW_TITLE'));
  113. $glEntry->short_name = $order['account_id'];
  114. $glEntry->ship_short_name = $order['account_id'];
  115. $glEntry->gl_acct_id = $order['gl_acct'];
  116. $glEntry->total_amount = $order['total_amount'];
  117. $glEntry->purchase_invoice_id = $order['order_id'];
  118. $glEntry->admin_id = $_SESSION['admin_id']; // set imported dept rep id to current logged in user
  119. if ($order['waiting']) $glEntry->waiting = '1';
  120. $glEntry->bill_primary_name = $order['bill_primary_name'];
  121. $glEntry->bill_contact = $order['bill_contact'];
  122. $glEntry->bill_address1 = $order['bill_address1'];
  123. $glEntry->bill_address2 = $order['bill_address2'];
  124. $glEntry->bill_city_town = $order['bill_city_town'];
  125. $glEntry->bill_state_province = $order['bill_state_province'];
  126. $glEntry->bill_postal_code = $order['bill_postal_code'];
  127. $glEntry->bill_country_code = $order['bill_country_code'];
  128. $glEntry->bill_telephone1 = $order['telephone1'];
  129. $glEntry->bill_telephone2 = $order['telephone2'];
  130. $glEntry->bill_fax = $order['fax'];
  131. $glEntry->bill_email = $order['email'];
  132. $glEntry->bill_website = $order['website'];
  133. switch (JOURNAL_ID) {
  134. case 4:
  135. case 6:
  136. $glEntry->ship_primary_name = COMPANY_NAME;
  137. $glEntry->ship_address1 = COMPANY_ADDRESS1;
  138. $glEntry->ship_address2 = COMPANY_ADDRESS2;
  139. $glEntry->ship_city_town = COMPANY_CITY_TOWN;
  140. $glEntry->ship_state_province = COMPANY_ZONE;
  141. $glEntry->ship_postal_code = COMPANY_POSTAL_CODE;
  142. $glEntry->ship_country_code = COMPANY_COUNTRY;
  143. break;
  144. default:
  145. $glEntry->ship_primary_name = $order['ship_primary_name'];
  146. $glEntry->ship_contact = $order['ship_contact'];
  147. $glEntry->ship_address1 = $order['ship_address1'];
  148. $glEntry->ship_address2 = $order['ship_address2'];
  149. $glEntry->ship_city_town = $order['ship_city_town'];
  150. $glEntry->ship_state_province = $order['ship_state_province'];
  151. $glEntry->ship_postal_code = $order['ship_postal_code'];
  152. $glEntry->ship_country_code = $order['ship_country_code'];
  153. }
  154. $glEntry->journal_main_array = $glEntry->build_journal_main_array();
  155. $glEntry->journal_main_array['purchase_invoice_id'] = $order['order_id']; // skip validating the invoice ID, just set it
  156. // Create the account (or update it)
  157. $glEntry->bill_acct_id = $glEntry->add_account(BB_ACCOUNT_TYPE . 'b', 0, 0, true);
  158. switch (JOURNAL_ID) {
  159. default: // update the shipping address
  160. $glEntry->ship_acct_id = $glEntry->add_account(BB_ACCOUNT_TYPE . 's', 0, 0, true);
  161. break;
  162. case 4: // skip for purchases (assume default company address)
  163. case 6:
  164. }
  165. // build journal row entries (2) one for the AP/AR account and the other for the beg bal equity account
  166. $glEntry->journal_rows = array();
  167. $total_amount = 0;
  168. while(true) {
  169. $credit_debit = false;
  170. switch (JOURNAL_ID) {
  171. case 4: $credit_debit = 'debit_amount'; // for journal_id = 4
  172. case 10: if (!$credit_debit) $credit_debit = 'credit_amount'; // for journal_id = 10
  173. $glEntry->journal_rows[] = array(
  174. 'gl_type' => BB_GL_TYPE,
  175. 'qty' => $currencies->clean_value($order['quantity']),
  176. 'sku' => $order['sku'],
  177. 'description' => $order['description'],
  178. 'gl_account' => $order['inv_gl_acct'],
  179. 'taxable' => $order['taxable'] ? $order['taxable'] : 0,
  180. $credit_debit => $currencies->clean_value($order['total_cost']),
  181. 'post_date' => $order['post_date'],
  182. );
  183. break;
  184. case 6: $credit_debit = 'debit_amount'; // for journal_id = 6
  185. case 12: if (!$credit_debit) $credit_debit = 'credit_amount'; // for journal_id = 12
  186. $glEntry->journal_rows[] = array(
  187. 'gl_type' => BB_GL_TYPE,
  188. 'qty' => '1',
  189. 'description' => constant('ORD_TEXT_' . JOURNAL_ID . '_WINDOW_TITLE') . '-' . TEXT_IMPORT,
  190. 'gl_account' => $order['inv_gl_acct'],
  191. 'taxable' => $order['taxable'] ? $order['taxable'] : 0,
  192. $credit_debit => $currencies->clean_value($order['total_amount']),
  193. 'post_date' => $order['post_date'],
  194. );
  195. break;
  196. }
  197. $total_amount += $currencies->clean_value($order['total_cost']);
  198. $next_order = $this->records[$row_cnt + 1]['order_id'];
  199. if ((JOURNAL_ID == 4 || JOURNAL_ID == 10) && $order['order_id'] == $next_order) { // more line items
  200. $row_cnt++;
  201. $order = $this->records[$row_cnt];
  202. } else { // end of this order, break from while(true) loop
  203. break;
  204. }
  205. }
  206. // build the total journal_item row
  207. switch (JOURNAL_ID) {
  208. case 6: $total_amount = $order['total_amount']; // and continue
  209. case 4: $debit_credit = 'credit_amount'; break;
  210. case 12: $total_amount = $order['total_amount']; // and continue
  211. case 10: $debit_credit = 'debit_amount'; break;
  212. }
  213. $glEntry->journal_rows[] = array(
  214. 'gl_type' => 'ttl',
  215. 'description' => constant('ORD_TEXT_' . $glEntry->journal_id . '_WINDOW_TITLE') . '-' . TEXT_TOTAL,
  216. 'gl_account' => $order['gl_acct'],
  217. $debit_credit => $total_amount,
  218. 'post_date' => $post_date,
  219. );
  220. $glEntry->journal_main_array['total_amount'] = $total_amount;
  221. if (!$glEntry->Post('insert')) return false;
  222. $entry_count++;
  223. $row_cnt++;
  224. }
  225. $this->line_count = $entry_count;
  226. return true;
  227. }
  228. function processInventory($upload_name) {
  229. global $coa, $db, $currencies, $messageStack;
  230. if (!$this->cyberParse($upload_name)) return false;
  231. $post_date = gen_specific_date(date('Y-m-d'), $day_offset = -1);
  232. $glEntry = new journal();
  233. $sku_list = array();
  234. $coa_list = array();
  235. $affected_accounts = array();
  236. for ($row_id = 0, $j = 2; $row_id < count($this->records); $row_id++, $j++) {
  237. $row = $this->records[$row_id];
  238. $total_amount = $currencies->clean_value($row['total_amount']);
  239. $qty = $currencies->clean_value($row['quantity']);
  240. // check for errors and report/exit if error found
  241. if (!gen_validate_sku($row['sku'])) {
  242. $messageStack->add(GL_ERROR_UPDATING_INVENTORY_STATUS . $row['sku'] . GL_BEG_BAL_ERROR_0 . $j, 'error');
  243. return false;
  244. }
  245. if (!in_array($row['inv_gl_acct'], $coa) || !in_array($row['gl_acct'], $coa)) {
  246. $messageStack->add(GL_BEG_BAL_ERROR_6 . $j, 'error');
  247. return false;
  248. }
  249. if ($qty == 0) {
  250. $messageStack->add(GL_BEG_BAL_ERROR_7 . $j,'caution');
  251. } else {
  252. $affected_accounts[$row['inv_gl_acct']] = true; // need list of accounts to update history
  253. $affected_accounts[$row['gl_acct']] = true; // both credit and debit
  254. $sku_list[$row['sku']]['qty'] += $qty; // load quantity indexed by sku
  255. $sku_list[$row['sku']]['total'] += $total_amount; // load total_value indexed by sku
  256. $coa_list[$row['inv_gl_acct']] += $total_amount; // add to debit total by coa
  257. $coa_list[$row['gl_acct']] -= $total_amount; // add to credit total by coa
  258. }
  259. }
  260. if (is_array($sku_list)) {
  261. $glEntry->affected_accounts = $affected_accounts;
  262. // *************** START TRANSACTION *************************
  263. $db->transStart();
  264. // update inventory balances on hand
  265. foreach ($sku_list as $sku => $details) {
  266. $sql = "update " . TABLE_INVENTORY . "
  267. set quantity_on_hand = quantity_on_hand + " . $details['qty'] . " where sku = '" . $sku . "'";
  268. $result = $db->Execute($sql);
  269. if ($result->AffectedRows() <> 1) {
  270. $messageStack->add(sprintf(GL_BEG_BAL_ERROR_8, $sku),'error');
  271. $db->transRollback();
  272. return false;
  273. }
  274. $history_array = array(
  275. 'ref_id' => 0,
  276. 'sku' => $sku,
  277. 'qty' => $details['qty'],
  278. 'remaining' => $details['qty'],
  279. 'unit_cost' => ($details['total'] / $details['qty']),
  280. 'post_date' => $post_date,
  281. );
  282. $result = db_perform(TABLE_INVENTORY_HISTORY, $history_array, 'insert');
  283. }
  284. // update chart of account beginning balances for period 1
  285. foreach ($coa_list as $account => $amount) {
  286. $sql = "update " . TABLE_CHART_OF_ACCOUNTS_HISTORY . " set beginning_balance = beginning_balance + " . $amount . "
  287. where account_id = '" . $account . "' and period = 1";
  288. $result = $db->Execute($sql);
  289. if ($result->AffectedRows() <> 1) {
  290. $messageStack->add(sprintf(GL_BEG_BAL_ERROR_9, $account),'error');
  291. $db->transRollback();
  292. return false;
  293. }
  294. }
  295. // update the chart of accounts history through the existing periods
  296. if (!$glEntry->update_chart_history_periods($period = 1)) {
  297. if (DEBUG) $messageStack->write_debug();
  298. return $glEntry->fail_message(GL_ERROR_UPDATE_COA_HISTORY);
  299. }
  300. $db->transCommit(); // post the chart of account values
  301. if (DEBUG) $messageStack->write_debug();
  302. // *************** END TRANSACTION *************************
  303. }
  304. $this->line_count = $row_id;
  305. return true;
  306. }
  307. }
  308. ?>