array('numeric'), 'name' => array('notempty'), ); var $belongsTo = array( 'PrimaryContact' => array( 'className' => 'Contact', ), ); var $hasMany = array( 'CurrentLease' => array( 'className' => 'Lease', 'conditions' => 'CurrentLease.close_date IS NULL', ), 'Lease', 'StatementEntry', 'ContactsCustomer', 'Transaction', ); var $hasAndBelongsToMany = array( 'Contact', ); /************************************************************************** ************************************************************************** ************************************************************************** * function: accountId * - Returns the account ID for the given customer */ function accountId($id) { $this->cacheQueries = true; $customer = $this->find('first', array('contain' => false, 'fields' => array('account_id'), 'conditions' => array(array('Customer.id' => $id)))); $this->cacheQueries = false; return $customer['Customer']['account_id']; } /************************************************************************** ************************************************************************** ************************************************************************** * function: leaseIds * - Returns the lease IDs for the given customer */ function leaseIds($id, $current = false) { $Lease = $current ? 'CurrentLease' : 'Lease'; $this->cacheQueries = true; $customer = $this->find('first', array('contain' => array($Lease => array('fields' => array('id'))), 'fields' => array(), 'conditions' => array(array('Customer.id' => $id)))); $this->cacheQueries = false; $ids = array(); foreach ($customer[$Lease] AS $lease) $ids[] = $lease['id']; return $ids; } /************************************************************************** ************************************************************************** ************************************************************************** * function: securityDeposits * - Returns an array of security deposit entries */ function securityDeposits($id, $query = null) { $this->prEnter(compact('id', 'query')); $this->queryInit($query); $query['conditions'][] = array('StatementEntry.customer_id' => $id); $query['conditions'][] = array('StatementEntry.account_id' => $this->StatementEntry->Account->securityDepositAccountID()); $set = $this->StatementEntry->reconciledSet('CHARGE', $query, false, true); return $this->prReturn($set); } /************************************************************************** ************************************************************************** ************************************************************************** * function: securityDepositBalance * - Returns the balance of the customer security deposit(s) */ function securityDepositBalance($id, $query = null) { $this->prEnter(compact('id', 'query')); $this->queryInit($query); $sd_account_id = $this->StatementEntry->Account->securityDepositAccountID(); $squery = $query; $squery['conditions'][] = array('StatementEntry.customer_id' => $id); $squery['conditions'][] = array('StatementEntry.account_id' => $sd_account_id); $stats = $this->StatementEntry->stats(null, $squery); $this->pr(26, compact('squery', 'stats')); // OK, we know now how much we charged for a security // deposit, as well as how much we received to pay for it. // Now we need to know if any has been released. // Yes... this sucks. $lquery = $query; $lquery['link'] = array('Transaction' => array('fields' => array(), 'Customer' => (empty($query['link']) ? array('fields' => array()) : $query['link']))); $lquery['conditions'][] = array('Transaction.customer_id' => $id); $lquery['conditions'][] = array('LedgerEntry.account_id' => $sd_account_id); $lquery['conditions'][] = array('LedgerEntry.crdr' => 'DEBIT'); $lquery['fields'][] = 'SUM(LedgerEntry.amount) AS total'; $released = $this->StatementEntry->Transaction->LedgerEntry->find ('first', $lquery); $this->pr(26, compact('lquery', 'released')); return $this->prReturn($stats['Charge']['disbursement'] - $released[0]['total']); } /************************************************************************** ************************************************************************** ************************************************************************** * function: unreconciledCharges * - Returns charges have not yet been fully paid */ function unreconciledCharges($id, $query = null) { $this->prEnter(compact('id', 'query')); $this->queryInit($query); $query['conditions'][] = array('StatementEntry.customer_id' => $id); $set = $this->StatementEntry->reconciledSet('CHARGE', $query, true); return $this->prReturn($set); } /************************************************************************** ************************************************************************** ************************************************************************** * function: saveCustomer * - Saves the customer and related data */ function saveCustomer($id, $data, $primary_contact_entry) { // Go through each contact, and create new ones as needed foreach ($data['Contact'] AS &$contact) { if (isset($contact['id'])) continue; $I = new Contact(); if (!$I->saveContact(null, array('Contact' => $contact))) return false; $contact['id'] = $I->id; } // Set the primary contact ID based on caller selection $data['Customer']['primary_contact_id'] = $data['Contact'][$primary_contact_entry]['id']; // Provide a default customer name if not specified if (!$data['Customer']['name']) { $this->Contact->recursive = -1; $pcontact = $this->Contact->read(null, $data['Customer']['primary_contact_id']); $data['Customer']['name'] = $pcontact['Contact']['display_name']; } // Save the customer data $this->create(); if ($id) $this->id = $id; if (!$this->save($data, false)) { return false; } $id = $this->id; // Appears that $this->save() "helpfully" choses to add in // any missing data fields, populated with default values. // So, after saving is complete, the fields 'lease_count', // 'past_lease_count', and 'current_lease_count' have all // been reset to zero. Gee, thanks Cake... $this->update($id); // Remove all associated Customer Contacts, as it ensures // any entries deleted by the user actually get deleted // in the system. We'll recreate the needed ones anyway. // REVISIT : 20090706 // Appears that $this->save() is already doing the // delete. I would have thought this would only happen // on a saveAll?? /* $this->ContactsCustomer->deleteAll */ /* (array('customer_id' => $id), false); */ // At this point, since we've saved data to customer, // we'll proceed forward as much as possible, even // if we encounter an error. For now, we'll assume // the operation will succeed. $ret = true; // Go through each entry of this customer method foreach ($data['Contact'] AS &$contact) { // Update the ContactsCustomer to reflect the appropriate IDs $contact['ContactsCustomer']['customer_id'] = $id; $contact['ContactsCustomer']['contact_id'] = $contact['id']; // Save the relationship between customer and contact $CM = new ContactsCustomer(); if (!$CM->save($contact['ContactsCustomer'], false)) { $ret = false; } } // Return the result return $ret; } /************************************************************************** ************************************************************************** ************************************************************************** * function: update * - Update any cached or calculated fields */ function update($id) { $this->prEnter(compact('id')); if (empty($id)) { $customers = $this->find('all', array('contain' => false, 'fields' => array('id'))); foreach ($customers AS $customer) { // This SHOULDN'T happen, but check to be sure // or we'll get infinite recursion. if (empty($customer['Customer']['id'])) continue; $this->update($customer['Customer']['id']); } return; } // updateLeaseCount is typically handled directly when needed. // However, this function is used to _ensure_ customer info is // current, so we're obligated to call it anyway. $this->updateLeaseCount($id); $current_leases = $this->find('all', // REVISIT : 20090816 // Do we need to update leases other than the current ones? // It may be necessary. For example, a non-current lease // can still be hit with an NSF item. In that case, it // could have stale data if we look only to current leases. //array('link' => array('CurrentLease' => array('type' => 'INNER')), array('link' => array('Lease' => array('type' => 'INNER')), 'conditions' => array('Customer.id' => $id))); foreach ($current_leases AS $lease) { if (!empty($lease['CurrentLease']['id'])) $this->Lease->update($lease['CurrentLease']['id']); if (!empty($lease['Lease']['id'])) $this->Lease->update($lease['Lease']['id']); } } /************************************************************************** ************************************************************************** ************************************************************************** * function: updateLeaseCount * - Updates the internal lease count */ function updateLeaseCount($id) { $this->id = $id; $lease_count = $this->find('count', array('link' => array('Lease' => array('type' => 'INNER')), 'conditions' => array('Customer.id' => $id))); $current_count = $this->find('count', array('link' => array('CurrentLease' => array('type' => 'INNER')), 'conditions' => array('Customer.id' => $id))); $this->saveField('lease_count', $lease_count); $this->saveField('current_lease_count', $current_count); $this->saveField('past_lease_count', $lease_count - $current_count); } /************************************************************************** ************************************************************************** ************************************************************************** * function: balance * - Returns the balance of money owed on the lease */ function balance($id) { $stats = $this->stats($id); return $stats['balance']; } /************************************************************************** ************************************************************************** ************************************************************************** * function: stats * - Returns summary data from the requested customer. */ function stats($id = null, $query = null) { //$this->prFunctionLevel(20); $this->prEnter(compact('id', 'query')); if (!$id) return $this->prExit(null); $this->queryInit($query); // REVISIT : 20090725 // We'll need to go directly to the statement entries if // transactions are not always associated with the customer. // This could happen if either we remove the customer_id // field from Transaction, or we allow multiple customers // to be part of the same transaction (essentially making // the Transaction.customer_id meaningless). /* $stats = $this->StatementEntry->find */ /* ('first', array */ /* ('contain' => false, */ /* 'fields' => $this->StatementEntry->chargeDisbursementFields(true), */ /* 'conditions' => array('StatementEntry.customer_id' => $id), */ /* )); */ $find_stats = $this->StatementEntry->find ('first', array ('contain' => false, 'fields' => $this->StatementEntry->chargeDisbursementFields(true), 'conditions' => array('StatementEntry.customer_id' => $id), )); $find_stats = $find_stats[0]; $this->pr(17, compact('find_stats')); $tquery = $query; $tquery['conditions'][] = array('StatementEntry.customer_id' => $id); $statement_stats = $this->StatementEntry->stats(null, $tquery); $statement_stats['balance'] = $statement_stats['Charge']['balance']; $this->pr(17, compact('statement_stats')); $tquery = $query; //$tquery['conditions'][] = array('StatementEntry.customer_id' => $id); $tquery['conditions'][] = array('Transaction.customer_id' => $id); $transaction_stats = $this->Transaction->stats(null, $tquery); $transaction_stats += $transaction_stats['StatementEntry']; $this->pr(17, compact('transaction_stats')); $tquery = $query; //$tquery['conditions'][] = array('StatementEntry.customer_id' => $id); $tquery['conditions'][] = array('Transaction.customer_id' => $id); $ar_transaction_stats = $this->Transaction->stats(null, $tquery, $this->Transaction->Account->accountReceivableAccountID()); $ar_transaction_stats += $ar_transaction_stats['LedgerEntry']; $this->pr(17, compact('ar_transaction_stats')); //$stats = $ar_transaction_stats; $stats = $find_stats; return $this->prReturn($stats); } } ?>