credit | + asset => debit class Finance { private $balanced_account_types; private $asset_account_types; private $liability_account_types; function __Construct() { $this->balanced_account_types = array('Bank','Cash','Other Current Assets','Fixed Assets','Accounts Payable','Other Current Liabilities','Equity'); $this->asset_account_types = array('Bank','Cash','Other Current Assets','Fixed Assets','Equity'); $this->liability_account_types = array('Accounts Payable','Other Current Liabilities'); } function get_account_id_by_name($name, $biz='hb') { $record = $this->get_account_record('', 'name', $name, $biz); return($record['id']); } function get_account_record($id, $by='id', $name='', $biz='hb') { if($by == 'id' && $id != '') { return($this->get_account_record_by_id($id, $biz)); } elseif($by == 'name' && $name != '') { return($this->get_account_record_by_name($name, $biz)); } else { return(false); } } function is_balanced_account($account_type) { return(in_array($account_type, $this->balanced_account_types)); } function is_asset_account($account_type) { return(in_array($account_type, $this->asset_account_types)); } function is_liability_account($account_type) { return(in_array($account_type, $this->liability_account_types)); } function get_account_record_by_id($id, $biz='hb') { if(!Utilities::is_positive_int($id)) { Utilities::notify(Config::$finance_email, 'HB ERROR: Invalid account id passed to Finance::get_account_by_id', "id: $id\n\npage: ".Utilities::get_current_script(), '', '', '', false); return(false); } $db_table = ($biz == 'hb') ? Config::$db_tables['accounts'] : Config::$db_tables['accounts_ia']; $query = "SELECT * FROM $db_table WHERE id='".$id."'"; return(Database::ado_get_row($query, $title='Finance::get_account_record_by_id')); } function get_account_record_by_name($name, $biz='hb') { $db_table = ($biz == 'hb') ? Config::$db_tables['accounts'] : Config::$db_tables['accounts_ia']; $query = "SELECT * FROM $db_table WHERE account='".trim(addslashes($name))."'"; return(Database::ado_get_row($query, $title='Finance::get_account_record_by_name')); } function make_journal_entry($amount, $account_id_debit, $account_id_credit, $ref_number, $notes='', $trans_dt='NOW()', $biz='hb') { if(!is_numeric($amount)) { Utilities::notify(Config::$finance_email, 'HB ERROR: Non-numeric amount passed to Finance::make_journal_entry', "amount: $amount\naccount_id_debit: $account_id_debit\naccount_id_credit: $account_id_credit\nref_number: $ref_number\nbiz: $biz\n\npage: ".Utilities::get_current_script(), '', '', '', false); return(false); } if(!Utilities::is_positive_int($account_id_debit) || !Utilities::is_positive_int($account_id_credit)) { Utilities::notify(Config::$finance_email, 'HB ERROR: Invalid account id passed to Finance::make_journal_entry', "amount: $amount\naccount_id_debit: $account_id_debit\naccount_id_credit: $account_id_credit\nref_number: $ref_number\nbiz: $biz\n\npage: ".Utilities::get_current_script(), '', '', '', false); return(false); } // make this catch a faulty entry - at the same time figure out balance adjustments (will be adjusted later if nec) // + liab => credit | + asset => debit //??? what about equity?? MARCIE - year end thing - no need on a day to day basis // crediting a liability means adding the amount $account_debit_record = $this->get_account_record($account_id_debit); $account_credit_record = $this->get_account_record($account_id_credit); // if else logic ok? MARCIE what about equity accounts? // debit assets means increasing balance // credit liabilities means increasing balance /* if($this->is_asset_account($account_debit_record['account_type'])) { $debit_adjust_amount = $amount; if($this->is_asset_account($account_credit_record['account_type'])) { Utilities::notify(Config::$finance_email, 'HB ERROR: Invalid account types passed to Finance::make_journal_entry', "debit account: ".$account_debit_record['account']." ($account_id_debit) type ".$account_debit_record['account_type']."\ncredit account: ".$account_credit_record['account']." ($account_id_credit) type ".$account_credit_record['account_type']." amount: $amount\nref_number: $ref_number\nbiz: $biz\n\npage: ".Utilities::get_current_script(), '', '', '', false); return(false); } $credit_adjust_amount = -$amount; } else { $debit_adjust_amount = -$amount; if($this->is_liability_account($account_credit_record['account_type'])) { Utilities::notify(Config::$finance_email, 'HB ERROR: Invalid account types passed to Finance::make_journal_entry', "debit account: ".$account_debit_record['account']." ($account_id_debit) type ".$account_debit_record['account_type']."\ncredit account: ".$account_credit_record['account']." ($account_id_credit) type ".$account_credit_record['account_type']." amount: $amount\nref_number: $ref_number\nbiz: $biz\n\npage: ".Utilities::get_current_script(), '', '', '', false); return(false); } $credit_adjust_amount = $amount; } */ $db_table = ($biz == 'hb') ? Config::$db_tables['general_journal'] : Config::$db_tables['general_journal_ia']; $insert_fields = array( 'id'=>'NULL', 'trans_dt'=>$trans_dt, 'amount'=>$amount, 'notes'=>$notes, 'ref_number'=>$ref_number, 'account_debit'=>$account_id_debit, 'account_credit'=>$account_id_credit); Database::_insert($db_table, $insert_fields); // adjust balance if nec if($this->is_balanced_account($account_debit_record['account_type'])) { $this->adjust_account_balance($account_id_debit, $debit_adjust_amount, $biz); } if($this->is_balanced_account($account_credit_record['account_type'])) { $this->adjust_account_balance($account_id_credit, $credit_adjust_amount, $biz); } } function adjust_account_balance($account_id, $amount, $biz='hb') { if(!is_numeric($amount)) { Utilities::notify(Config::$finance_email, 'HB ERROR: Non-numeric amount passed to Finance::adjust_account_balance', "amount: $amount\naccount id: $account_id\nbiz: $biz\n\npage: ".Utilities::get_current_script(), '', '', '', false); return(false); } if(!Utilities::is_positive_int($account_id)) { Utilities::notify(Config::$finance_email, 'HB ERROR: Invalid account id passed to Finance::make_journal_entry', "account_id: $account_id\namount: $amount\n\npage: ".Utilities::get_current_script(), '', '', '', false); return(false); } $db_table = ($biz == 'hb') ? Config::$db_tables['accounts'] : Config::$db_tables['accounts_ia']; Database::ado_execute_query("UPDATE $db_table SET balance = balance + $amount WHERE id='$account_id' LIMIT 1"); // also update the balance on the parent account if any $parent_id = $this->get_parent($account_id, $biz); if($parent_id > 0) { Database::ado_execute_query("UPDATE $db_table SET balance = balance + $amount WHERE id='$parent_id' LIMIT 1"); } } function get_parent($account_id, $biz='hb') { $db_table = ($biz == 'hb') ? Config::$db_tables['accounts'] : Config::$db_tables['accounts_ia']; return(Database::ado_get_one("SELECT parent FROM $db_table WHERE id='$account_id'")); } function receive_inventory_shipment($amount, $invoiced=false, $invoice_id='',$shipment_id='') { // debit inventory account // credit A/P - Inventory Invoiced account or A/P - Inventory To Be Invoiced // if invoiced the amount will be total invoice amount, otherwise amount will be items amount //?? MARCIE - do i need to make a journal entry for A/P - the parent? NO if($invoiced) { $credit_account = 'A/P - Inventory Invoiced'; $ref_field = $invoice_id; $notes_field = 'invoice id'; } else { $credit_account = 'A/P - Inventory To Be Invoiced'; $ref_field = $shipment_id; $notes_field = 'shipment id'; } $this->make_journal_entry($amount, $this->get_account_id_by_name('Inventory'), $this->get_account_id_by_name('A/P - Inventory To Be Invoiced'), $ref_field, $notes_field); } function receive_shipment_invoice($invoice_id, $items_amount, $shipping_amount, $other_amount) { // debit inventory account for shipping + other amount // credit A/P - Inventory Invoiced for shipping + other amount //-------------- // debit A/P - Inventory To Be Invoiced for items amount // credit A/P - Inventory Invoiced for items amount //-------------- //?? MARCIE - do i need to make a journal entry for A/P - the parent? NO $non_items_amount = $shipping_amount + $other_amount; $this->make_journal_entry($non_items_amount, $this->get_account_id_by_name('Inventory'), $this->get_account_id_by_name('A/P - Inventory Invoiced'), $invoice_id, 'invoice id'); ///////////////////// $this->make_journal_entry($items_amount, $this->get_account_id_by_name('A/P - Inventory To Be Invoiced'), $this->get_account_id_by_name('A/P - Inventory Invoiced'), $invoice_id, 'invoice id'); } function journal_order_payment($transaction_id, $amount, $method, $biz='hb') { switch($method) { case 'cash': $ufAcct = 'Undeposited Funds - Cash'; break; case 'check': $ufAcct = 'Undeposited Funds - Check'; break; case 'm': $ufAcct = 'Undeposited Funds - M/V'; break; case 'a': $ufAcct = 'Undeposited Funds - A'; break; case 'disc': $ufAcct = 'Undeposited Funds - Disc'; break; case 'debit': $ufAcct = 'Undeposited Funds - Debit'; break; } $this->make_journal_entry($amount, $this->get_account_id_by_name($ufAcct), $this->get_account_id_by_name('Sales'), $transaction_id, 'transaction id', $biz); } function journal_item_sale($order_item_id, $cost, $qty, $biz='hb') { // debit cgs / credit inv $amount = $qty * $cost; $this->make_journal_entry($amount, $this->get_account_id_by_name('Cost Of Goods Sold'), $this->get_account_id_by_name('Inventory'), $order_item_id, 'order item id', $biz); } function journal_sale($order_id, $sale_total, $payments_total, $payments, $items, $biz='hb') { // what about for inventory we don't have yet?? MARCIE?? - that's an order not a sale - do the sale when we do transaction // what about layaways? foreach($payments as $payment) { $this->journal_order_payment($payment['transaction_id'], $payment['amount'], $payment['method']); } $unpaid_amount = round($sale_total - $payments_total, 2); // any layaway amount - debit UF / credit Layaway Deposits -> no inventory accounting if($unpaid_amount > 0) { } foreach($items as $item) { // how to determine item cost?? MARCIE -> ** FIFO or average cost $this->journal_item_sale($item['order_item_id'], $item['cost'], $item['qty'], $biz='hb'); } } function journal_invoice_payment($invoice_id, $amount, $method) { } } // + liab => credit | + asset => debit ?>