00001 <?php
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 require_once FASTFRAME_ROOT . 'lib/FastFrame/DataAccess.php';
00027 require_once dirname(__FILE__) . '/../../Model/Log.php';
00028
00029
00030
00031
00032
00033 define('LOANS_TYPE_LOAN', 1);
00034 define('LOANS_TYPE_RESERVATION', 2);
00035 define('LOANS_TYPE_CART', 3);
00036 define('LOANS_TYPE_SHOP_CART', 4);
00037
00038 define('LOANS_TYPE_RETURN', -1);
00039
00040
00041 define('LOANS_FILTER_RESERVATIONS', 1);
00042 define('LOANS_FILTER_LOANS', 2);
00043 define('LOANS_FILTER_LOANS_BORROWER', 3);
00044 define('LOANS_FILTER_CARTS', 4);
00045 define('LOANS_FILTER_BORROWER', 5);
00046 define('LOANS_FILTER_ITEM', 6);
00047 define('LOANS_FILTER_GROUP', 7);
00048 define('LOANS_FILTER_ALL', 8);
00049
00050
00051
00052
00063
00064 class FF_DataAccess_Loan_mysql extends FF_DataAccess {
00065
00066
00071 var $transactionTable;
00072
00077 var $borrowerTable;
00078
00079
00084 var $o_log;
00085
00090 var $filterName;
00091
00092
00093
00094
00101 function FF_DataAccess_Loan_mysql()
00102 {
00103 FF_DataAccess::FF_DataAccess();
00104 $this->table = $this->o_registry->getConfigParam('data/loans_table');
00105 $this->transactionTable = $this->o_registry->getConfigParam('data/transaction_items_table');
00106 $this->borrowerTable = $this->o_registry->getConfigParam('data/borrowers_table');
00107 $this->o_log =& new FF_Model_Log();
00108 }
00109
00110
00111
00112
00124 function getListData($in_where, $in_orderByField, $in_orderByDir, $in_fields = '*')
00125 {
00126 if ($this->filterName == LOANS_FILTER_LOANS ||
00127 $this->filterName == LOANS_FILTER_LOANS_BORROWER ||
00128 $this->filterName == LOANS_FILTER_ITEM ||
00129 $this->filterName == LOANS_FILTER_GROUP) {
00130 $s_query = "SELECT " . $this->_getSelectFields() . " FROM $this->table AS l
00131 INNER JOIN $this->transactionTable AS t ON l.id = t.transaction_id
00132 LEFT JOIN $this->borrowerTable AS b ON l.borrower_id = b.id
00133 WHERE $in_where GROUP BY l.id ORDER BY $in_orderByField " .
00134 $this->_getOrderByDirection($in_orderByDir);
00135 }
00136 else {
00137 $s_query = "SELECT " . $this->_getSelectFields() . " FROM $this->table AS l
00138 LEFT JOIN $this->borrowerTable AS b ON l.borrower_id = b.id
00139 WHERE $in_where ORDER BY $in_orderByField " .
00140 $this->_getOrderByDirection($in_orderByDir);
00141 }
00142
00143 return $this->o_data->query($s_query);
00144 }
00145
00146
00147
00148
00161 function getListFilter($in_searchString, $in_searchFields, $in_filter, $in_filterData)
00162 {
00163
00164 $this->filterName = $in_filter;
00165
00166 if ($this->filterName == LOANS_FILTER_RESERVATIONS) {
00167 $s_filter = sprintf('l.type = %s', LOANS_TYPE_RESERVATION);
00168 }
00169
00170 elseif ($this->filterName == LOANS_FILTER_LOANS ||
00171 $this->filterName == LOANS_FILTER_LOANS_BORROWER) {
00172 $s_filter = sprintf('l.type = %s AND t.return_date = 0', LOANS_TYPE_LOAN);
00173
00174 if ($this->filterName == LOANS_FILTER_LOANS_BORROWER) {
00175 $s_filter .= sprintf(' AND l.borrower_id = %s', $this->o_data->quoteSmart($in_filterData['borrowerId']));
00176 }
00177 }
00178
00179 elseif ($this->filterName == LOANS_FILTER_BORROWER) {
00180 $s_filter = sprintf('l.borrower_id = %s AND l.type < %s',
00181 $this->o_data->quoteSmart($in_filterData['borrowerId']), LOANS_TYPE_CART);
00182 }
00183
00184 elseif ($this->filterName == LOANS_FILTER_ITEM) {
00185 $s_filter = sprintf('l.type < %s AND t.item_id = %s',
00186 LOANS_TYPE_CART, $this->o_data->quoteSmart($in_filterData['itemId']));
00187 }
00188
00189 elseif ($this->filterName == LOANS_FILTER_GROUP) {
00190 $o_groupDataAccess =& FF_DataAccess::factory('Group');
00191 $s_filter = '';
00192 foreach ($o_groupDataAccess->getGroupItems($in_filterData['groupId']) as $a_item) {
00193 $s_filter .= sprintf('t.item_id = %s OR ', $a_item['item_id']);
00194 }
00195
00196 $s_filter .= '0=1';
00197 $s_filter = sprintf('l.type < %s AND (t.item_id = %s OR %s)',
00198 LOANS_TYPE_CART, $this->o_data->quoteSmart($in_filterData['groupId']), $s_filter);
00199 }
00200
00201 elseif ($this->filterName == LOANS_FILTER_CARTS) {
00202 $s_filter = sprintf('l.type = %s AND l.due_date > NOW()', LOANS_TYPE_CART);
00203 }
00204
00205 elseif ($this->filterName == LOANS_FILTER_ALL) {
00206 $s_filter = sprintf('l.type < %s', LOANS_TYPE_CART);
00207 }
00208
00209 if ($this->filterName != LOANS_FILTER_ALL && $this->filterName != LOANS_FILTER_BORROWER) {
00210 $s_filter .= ' AND l.deleted != 1 AND ';
00211 }
00212 else {
00213 $s_filter .= ' AND ';
00214 }
00215
00216 $s_filter .= '(' . parent::getListFilter($in_searchString, $in_searchFields, $in_filter, $in_filterData) . ')';
00217
00218
00219 $s_filter = preg_replace('/`borrower_name` BETWEEN .*? OR/', '', $s_filter);
00220
00221 $s_filter = preg_replace('/`borrower_name` LIKE \'%(.*?)%\'/',
00222 'b.first_name LIKE \'\\1%\' OR b.last_name LIKE \'\\1%\'', $s_filter);
00223 $s_filter = preg_replace('/`(.*?)`/', 'l.\\1', $s_filter);
00224
00225 $a_map = array(_('loan') => LOANS_TYPE_LOAN, _('reservation') => LOANS_TYPE_RESERVATION,
00226 _('cart') => LOANS_TYPE_CART, _('shopping cart') => LOANS_TYPE_SHOP_CART);
00227
00228 $s_filter = preg_replace('/(l.type LIKE \'%)(.*?)(%\')/e',
00229 '\'\\1\' . (isset($a_map[strtolower(\'\\2\')]) ? $a_map[strtolower(\'\\2\')] : \'-1\') . \'\\3\'',
00230 $s_filter);
00231 return $s_filter;
00232 }
00233
00234
00235
00236
00246 function getDataByPrimaryKey($in_id, $in_fields = '*')
00247 {
00248 $s_query = "SELECT " . $this->_getSelectFields() . " FROM $this->table AS l
00249 LEFT JOIN $this->borrowerTable AS b ON l.borrower_id = b.id
00250 WHERE l.id = ?";
00251 if (DB::isError($result = $this->o_data->getAll($s_query, array($in_id)))) {
00252 return array();
00253 }
00254 else {
00255 return @$result[0];
00256 }
00257 }
00258
00259
00260
00261
00270 function update($in_data)
00271 {
00272 $s_query = "SELECT type FROM $this->table WHERE id = ?";
00273 $s_origType = $this->o_data->getOne($s_query, $in_data['id']);
00274
00275 $in_data['start_date'] = $this->timestampToISODate($in_data['start_date']);
00276 $in_data['due_date'] = $this->timestampToISODate($in_data['due_date']);
00277 $in_data['deleted'] = false;
00278 $s_override = $in_data['forceOverride'];
00279 $a_items = $in_data['items'];
00280 unset($in_data['overrideCode']);
00281 unset($in_data['forceOverride']);
00282 unset($in_data['items']);
00283 unset($in_data['itemsToRemove']);
00284 unset($in_data['newComment']);
00285 $o_result =& parent::update($in_data);
00286 if ($o_result->isSuccess()) {
00287 if ($s_override) {
00288 $tmp_result =& $this->o_log->newLogEntry('FORCE_OVERRIDE', $in_data['id'], $this->table);
00289 }
00290
00291 if ($s_origType != $in_data['type']) {
00292 if ($in_data['type'] == LOANS_TYPE_RESERVATION) {
00293 $tmp_result =& $this->o_log->newLogEntry('RESERVATION', $in_data['id'], $this->table);
00294 }
00295 elseif ($in_data['type'] == LOANS_TYPE_LOAN) {
00296 $tmp_result =& $this->o_log->newLogEntry('LOAN', $in_data['id'], $this->table);
00297 }
00298 else {
00299 $tmp_result =& $this->o_log->newLogEntry('UPDATE', $in_data['id'], $this->table);
00300 }
00301 }
00302 else {
00303 $tmp_result =& $this->o_log->newLogEntry('UPDATE', $in_data['id'], $this->table);
00304 }
00305
00306 $this->addNewItems($in_data['id'], $a_items, $o_result);
00307 }
00308
00309 return $o_result;
00310 }
00311
00312
00313
00314
00323 function add($in_data)
00324 {
00325 $in_data['start_date'] = $this->timestampToISODate($in_data['start_date']);
00326 $in_data['due_date'] = $this->timestampToISODate($in_data['due_date']);
00327 $in_data['deleted'] = false;
00328 $a_items = $in_data['items'];
00329 unset($in_data['overrideCode']);
00330 unset($in_data['forceOverride']);
00331 unset($in_data['items']);
00332 unset($in_data['itemsToRemove']);
00333 unset($in_data['newComment']);
00334 $o_result =& parent::add($in_data);
00335 if ($o_result->isSuccess()) {
00336 if ($in_data['type'] == LOANS_TYPE_RESERVATION) {
00337 $tmp_result =& $this->o_log->newLogEntry('RESERVATION', $in_data['id'], $this->table);
00338 }
00339 else {
00340 $tmp_result =& $this->o_log->newLogEntry('INSERT', $in_data['id'], $this->table);
00341 }
00342
00343 $this->addNewItems($in_data['id'], $a_items, $o_result);
00344 }
00345
00346 return $o_result;
00347 }
00348
00349
00350
00351
00360 function remove($in_loanId)
00361 {
00362 $o_result = new FF_Result();
00363 $s_where = 'id=' . $this->o_data->quoteSmart($in_loanId);
00364 $result = $this->o_data->autoExecute($this->table, array('deleted' => true), DB_AUTOQUERY_UPDATE, $s_where);
00365 if (DB::isError($result)) {
00366 $o_result->addMessage($result->getMessage());
00367 $o_result->setSuccess(false);
00368 }
00369 else {
00370 $tmp_result =& $this->o_log->newLogEntry('DELETE', $in_loanId, $this->table);
00371 }
00372
00373 return $o_result;
00374 }
00375
00376
00377
00378
00395 function &getSummaryData($in_type, $in_shopperOnly, $in_borrowerSearch, $in_borrowerId)
00396 {
00397
00398 if ($in_type == LOANS_TYPE_LOAN && $in_shopperOnly) {
00399 $s_where = sprintf('l.type = %s AND t.return_date = 0 AND l.borrower_id = %s',
00400 LOANS_TYPE_LOAN, $this->o_data->quoteSmart($in_borrowerId));
00401 $s_limit = $this->o_registry->getConfigParam('checkout/summary_loan_limit');
00402 $s_order = 'due_date ASC';
00403 }
00404
00405 elseif ($in_type == LOANS_TYPE_LOAN) {
00406 $s_where = sprintf('l.type = %s AND (t.return_date = 0 OR (l.due_date >= %s AND t.return_date = 0))',
00407 LOANS_TYPE_LOAN, $this->o_data->quoteSmart($this->timestampToISODate(time() +
00408 ($this->o_registry->getConfigParam('checkout/loans_lookahead') * 3600))));
00409 $s_limit = $this->o_registry->getConfigParam('checkout/summary_loan_limit');
00410 $s_order = 'due_date ASC';
00411 }
00412
00413 elseif ($in_type == LOANS_TYPE_RESERVATION && $in_shopperOnly) {
00414 $s_where = sprintf('l.type = %s AND l.borrower_id = %s AND l.start_date > %s',
00415 LOANS_TYPE_RESERVATION, $this->o_data->quoteSmart($in_borrowerId),
00416 $this->o_data->quoteSmart($this->timestampToISODate(time() -
00417 ($this->o_registry->getConfigParam('checkout/reservations_lookahead') * 3600))));
00418 if (!FastFrame::isEmpty(FF_Request::getParam('chkoutStoreId', 's'))) {
00419 $s_where .= sprintf(' AND (l.store_id = %s OR l.store_id IS NULL)',
00420 $this->o_data->quoteSmart(FF_Request::getParam('chkoutStoreId', 's')));
00421 }
00422
00423 $s_limit = $this->o_registry->getConfigParam('checkout/summary_reservation_limit');
00424 $s_order = 'start_date ASC';
00425 }
00426
00427 elseif ($in_type == LOANS_TYPE_RESERVATION) {
00428 $s_where = sprintf('l.type = %s AND l.start_date BETWEEN %s AND %s',
00429 LOANS_TYPE_RESERVATION,
00430 $this->o_data->quoteSmart($this->timestampToISODate(time() -
00431 ($this->o_registry->getConfigParam('checkout/reservations_lookahead') * 3600))),
00432 $this->o_data->quoteSmart($this->timestampToISODate(time() +
00433 ($this->o_registry->getConfigParam('checkout/reservations_lookahead') * 3600))));
00434 $s_limit = $this->o_registry->getConfigParam('checkout/summary_reservation_limit');
00435 $s_order = 'start_date ASC';
00436 }
00437
00438 else {
00439 $s_where = sprintf('l.type = %s AND l.due_date > NOW()', LOANS_TYPE_CART);
00440 $s_limit = $this->o_registry->getConfigParam('checkout/summary_cart_limit');
00441 $s_order = 'start_date DESC';
00442 }
00443
00444 $s_where .= ' AND l.deleted != 1';
00445 if (!$in_shopperOnly && $in_borrowerSearch != '') {
00446 $s_where .= sprintf(' AND (b.first_name LIKE %1$s OR b.last_name LIKE %1$s)',
00447 $this->o_data->quoteSmart($in_borrowerSearch . '%'));
00448 }
00449
00450 if ($in_type == LOANS_TYPE_LOAN) {
00451 $s_query = "SELECT " . $this->_getSelectFields() . ", COUNT(l.id) AS numNotReturned
00452 FROM $this->table AS l
00453 INNER JOIN $this->transactionTable AS t ON l.id = t.transaction_id
00454 LEFT JOIN $this->borrowerTable AS b ON l.borrower_id = b.id
00455 WHERE $s_where GROUP BY l.id ORDER BY $s_order LIMIT 0, $s_limit";
00456 }
00457 else {
00458 $s_query = "SELECT " . $this->_getSelectFields() . " FROM $this->table AS l
00459 LEFT JOIN $this->borrowerTable AS b ON l.borrower_id = b.id
00460 WHERE $s_where ORDER BY $s_order LIMIT 0, $s_limit";
00461 }
00462
00463 return $this->o_data->query($s_query);
00464 }
00465
00466
00467
00468
00484 function getConflictingItems($in_id, $in_startDate, $in_endDate, $in_groups, $in_type, $in_onlyOnLoan, $in_itemFilter = null)
00485 {
00486 $s_startDateISO = $this->o_data->quoteSmart($this->timestampToISODate($in_startDate));
00487 $s_endDateISO = $this->o_data->quoteSmart($this->timestampToISODate($in_endDate));
00488 $s_timeConflict = "
00489 -- Does group in question fall in the bounds of another loan
00490 ( $s_startDateISO >= l.start_date AND $s_endDateISO <= l.due_date ) OR
00491 -- Does group in question have another loan that falls within its bounds
00492 ( $s_startDateISO <= l.start_date AND $s_endDateISO >= l.due_date ) OR
00493 -- Does group in question bridge the end date of another loan
00494 ( $s_startDateISO >= l.start_date AND $s_startDateISO <= l.due_date AND $s_endDateISO >= l.start_date ) OR
00495 -- Does group in question bridge the start date of another loan
00496 ( $s_startDateISO <= l.start_date AND $s_endDateISO <= l.due_date AND $s_endDateISO >= l.start_date )";
00497
00498
00499 if (!$in_groups && ($in_type == LOANS_TYPE_RESERVATION || $in_type == LOANS_TYPE_CART)) {
00500 $s_timeConflict = sprintf('(%s) AND NOT (l.type = %s AND t.return_date != 0)',
00501 $s_timeConflict, LOANS_TYPE_LOAN);
00502 }
00503 elseif (!$in_groups && $in_type == LOANS_TYPE_LOAN) {
00504 $s_timeConflict = sprintf('(%s) AND t.return_date = 0', $s_timeConflict);
00505 }
00506
00507 if ($in_groups) {
00508 $s_transid = 'item_id';
00509 $s_joinTable = $this->o_registry->getConfigParam('data/groups_table');
00510 $s_fields = 'j.name, j.is_kit';
00511
00512 }
00513 else {
00514 $s_transid = 'DISTINCT(t.item_id)';
00515 $s_joinTable = $this->o_registry->getConfigParam('data/items_table');
00516 $s_fields = 'j.name, j.barcode, j.status, 0 AS is_kit';
00517 }
00518
00519 if ($in_onlyOnLoan) {
00520 $s_typeClause = sprintf('l.type = %s', LOANS_TYPE_LOAN);
00521 }
00522 else {
00523 $s_typeClause = sprintf('l.type < %s', LOANS_TYPE_CART);
00524 }
00525
00526 $s_itemFilter = '';
00527 if (is_array($in_itemFilter) && count($in_itemFilter)) {
00528 $s_itemFilter = ' AND (item_id = ' . implode(' OR item_id = ', $in_itemFilter) . ')';
00529 }
00530
00531 settype($in_groups, 'int');
00532 $s_query = "SELECT $s_transid,
00533 UNIX_TIMESTAMP(t.return_date) AS return_date,
00534 GREATEST(UNIX_TIMESTAMP(l.start_date), $in_startDate) AS start_time,
00535 LEAST(UNIX_TIMESTAMP(l.due_date), $in_endDate) AS end_time,
00536 $in_groups AS is_group, $s_fields
00537 FROM $this->transactionTable as t
00538 INNER JOIN $this->table AS l ON t.transaction_id = l.id
00539 INNER JOIN $s_joinTable AS j ON t.item_id = j.id
00540 WHERE l.id != " . $this->o_data->quoteSmart($in_id) . " AND l.deleted = 0
00541 AND $s_typeClause AND is_group = $in_groups AND ($s_timeConflict) $s_itemFilter";
00542
00543 $a_items = $this->o_data->getAll($s_query);
00544 return $a_items;
00545 }
00546
00547
00548
00549
00560 function getNumOpen($in_borrowerId, $in_transactionId)
00561 {
00562 $a_totals = array();
00563 $s_query = "SELECT COUNT(DISTINCT l.id) FROM $this->table AS l
00564 INNER JOIN $this->transactionTable AS t ON l.id = t.transaction_id
00565 WHERE l.id \!= ? AND l.borrower_id = ? AND
00566 l.type = ? AND t.return_date = 0 AND l.deleted = 0";
00567
00568 $a_totals[0] = (int) $this->o_data->getOne($s_query,
00569 array($in_transactionId, $in_borrowerId, LOANS_TYPE_LOAN));
00570 $s_query = "SELECT COUNT(*) FROM $this->table
00571 WHERE id \!= ? AND borrower_id = ? AND
00572 type = ? AND due_date > NOW() AND deleted = 0";
00573
00574 $a_totals[1] = (int) $this->o_data->getOne($s_query,
00575 array($in_transactionId, $in_borrowerId, LOANS_TYPE_RESERVATION));
00576 return $a_totals;
00577 }
00578
00579
00580
00581
00592 function addNewItems($in_transactionId, $in_items, &$in_resultObj)
00593 {
00594 $o_transDataAccess =& FF_DataAccess::factory('Transaction');
00595 $a_existingItems = $o_transDataAccess->getItemIdsByTransactionId($in_transactionId);
00596 foreach ($in_items as $a_data) {
00597
00598
00599 if (!is_null($a_data['itemId']) &&
00600 ($a_data['isGroup'] ||
00601 (!$a_data['isGroup'] && !isset($a_existingItems[$a_data['itemId']])))) {
00602 $tmp_data = array(
00603 'transaction_id' => $in_transactionId,
00604 'item_id' => $a_data['itemId'],
00605 'return_date' => 0,
00606 'is_group' => $a_data['isGroup']);
00607 $o_result =& $o_transDataAccess->add($tmp_data);
00608 if (!$o_result->isSuccess()) {
00609 if ($a_data['isGroup']) {
00610 $in_resultObj->addMessage(sprintf(_('Error in adding group with id: %s'), $a_data['itemId']));
00611 }
00612 else {
00613 $in_resultObj->addMessage(sprintf(_('Error in adding item with id: %s'), $a_data['itemId']));
00614 }
00615
00616 $in_resultObj->setSuccess(false);
00617 }
00618 else {
00619
00620 $a_existingItems[$a_data['itemId']] = $a_data['isGroup'];
00621 }
00622 }
00623 }
00624 }
00625
00626
00627
00628
00635 function getNextId()
00636 {
00637
00638 $this->o_data->setOption('seqname_format', '%s');
00639 return $this->o_data->nextId($this->o_registry->getConfigParam('data/sequence_table'));
00640 }
00641
00642
00643
00644
00652 function _getSelectFields()
00653 {
00654 return 'l.id, UNIX_TIMESTAMP(l.start_date) AS start_date, UNIX_TIMESTAMP(l.due_date) AS due_date, l.borrower_id, l.type, l.created_by_shopper, l.store_id, l.is_complete, l.user_id, l.deleted, CONCAT(b.first_name, \' \', b.last_name) AS borrower_name';
00655 }
00656
00657
00658 }
00659 ?>