emo->loaded()) HTTP::redirect(URL::link('reseller','export/index')); $o = ORM::factory('Module',$this->emo->module_id); if (! $o->loaded()) HTTP::redirect(URL::link('reseller','export/index')); switch ($o->name) { case 'invoice': $output .= $this->invoices($_POST['id']); break; case 'payment': $output .= $this->payments($_POST['id']); break; default: throw HTTP_Exception::factory(501,'Dont know how to export :name',array(':name'=>$o->name)); } $response->body($output); $response->send_file(TRUE,'quicken-import.iif',array('mime_type'=>'text/plain')); } /** * Export an invoice */ private function invoice(Model_Invoice $io) { $defaults = array( 'ACCNT'=>'Accounts Receivable', 'TRNSTYPE'=>'TAX_INVOICE', 'INVMEMO'=>'Thank you for using '.Company::instance()->name(), 'CLEAR'=>'N', 'TOPRINT'=>'N', 'PAID'=>'N', 'MEMO'=>'Import from OSB', 'INVTITLE'=>Company::instance()->name().' Invoice', ); $invoice = $items = array(); $invoice['TRNSID'] = sprintf('%06s',$io->id); $invoice['DATE'] = date('m/d/Y',$io->date_orig); $invoice['ADDR1'] = $io->account->address1; $invoice['ADDR2'] = $io->account->address2; $invoice['ADDR3'] = sprintf('%s, %s %s',$io->account->city,$io->account->state,$io->account->zip); // @todo - should be configurable # $invoice['TERMS'] = '7 Days'; $invoice['DOCNUM'] = sprintf('%06s',$io->id); $invoice['DUEDATE'] = date('m/d/Y',$io->due_date); $invoice['AMOUNT'] = sprintf('%3.2f',$io->total()); $invoice['NAME'] = $io->account->company ? $io->account->company : sprintf('%s %s',$io->account->last_name,$io->account->first_name); // Other Quicken fields not used. #$invoice['CLASS'] = ''; #$invoice['SHIPVIA'] = ''; #$invoice['SHIPDATE'] = ''; #$invoice['OTHER1'] = ''; #$invoice['REP'] = ''; #$invoice['FOB'] = ''; #$invoice['PONUM'] = ''; #$invoice['SADDR1'] = ''; #$invoice['SADDR2'] = ''; #$invoice['SADDR3'] = ''; #$invoice['SADDR4'] = ''; #$invoice['SADDR5'] = ''; $c = 0; // Add the items to the invoice foreach ($io->subitems('CHARGE') as $iio) { // Skip any zero amount items not relating to a service if ($iio->total() == 0 and ! $iio->service_id) continue; // Get the mapping item for account purposes if ($iio->module() instanceof Model_Product) { $edo = ORM::factory('Export_DataMap') ->where('module_id','=',$iio->module_id) ->and_where('item_id','=',$iio->module_ref) ->find(); if ($edo->loaded()) { $items[$c]['ACCNT'] = $edo->map_data['account']; $items[$c]['INVITEM'] = $edo->map_data['item']; } else { throw HTTP_Exception::factory(501,'Missing product map data for :product (:id)',array(':product'=>$iio->product->name(Site::language()),':id'=>$iio->module_ref)); } $items[$c]['MEMO'] = $iio->name(); // Non product item } else { $items[$c]['ACCNT'] = 'Other Income'; $items[$c]['INVITEM'] = 'Unknown'; $items[$c]['MEMO'] = $iio->period(); } $items[$c]['CLEAR'] = 'N'; $items[$c]['QNTY'] = -1; if ($iio->tax_items()) { // @todo, need to figure out how multiple tax items are handled if (count($iio->tax_items()) > 1) throw HTTP_Exception(501,'Export cant handle multiple tax items yet'); foreach ($iio->tax_items() as $tid => $amount) { $to = ORM::factory('Tax',$tid); $items[$c]['TAXABLE'] = 'Y'; $items[$c]['TAXCODE'] = $to->description; $items[$c]['TAXRATE'] = sprintf('%3.2f%%',$to->rate); $items[$c]['TAXAMOUNT'] = sprintf('%3.2f',$amount*-1); } } else { $items[$c]['TAXAMOUNT'] = 0; } // @todo This rounding should be a system config. if ($iio->module() instanceof Model_Charge) { $items[$c]['QNTY'] *= $iio->module()->quantity; $items[$c]['PRICE'] = sprintf('%3.2f',round($iio->module()->amount-$iio->discount(),2)); $items[$c]['AMOUNT'] = sprintf('%3.2f',round($iio->subtotal()-$iio->discount(),2)*-1); } else { $items[$c]['PRICE'] = sprintf('%3.2f',round($iio->subtotal()-$iio->discount(),2)); $items[$c]['AMOUNT'] = sprintf('%3.2f',round($iio->subtotal()-$iio->discount(),2)*-1); } $c++; } // Add credits as a other item foreach ($io->subitems('CREDIT') as $iio) { $items[$c]['ACCNT'] = 'Other Income'; $items[$c]['INVITEM'] = 'Product:Unknown'; $items[$c]['CLEAR'] = 'N'; $items[$c]['QNTY'] = 1; $items[$c]['MEMO'] = 'Credit Item'; foreach ($iio->tax_items() as $tid => $amount) { $to = ORM::factory('Tax',$tid); $items[$c]['TAXABLE'] = 'Y'; $items[$c]['TAXCODE'] = $to->description; $items[$c]['TAXRATE'] = sprintf('%3.2f%%',$to->rate); $items[$c]['TAXAMOUNT'] = sprintf('%3.2f',$amount*-1); } $items[$c]['PRICE'] = sprintf('%3.2f',round($iio->subtotal()-$iio->discount(),2)); $items[$c]['AMOUNT'] = sprintf('%3.2f',round($iio->subtotal()-$iio->discount(),2)*-1); $c++; } return $this->output(Arr::merge($defaults,$invoice),$items); } /** * Export selected invoices */ private function invoices(array $ids) { $output = ''; foreach ($ids as $id) $output .= $this->invoice(ORM::factory('Invoice',$id)); // If all went OK, update our export status $this->update($ids); return $output; } /** * Return exported data for download */ private function output(array $trans,array $items) { $output = ''; $output .= "!TRNS\t"; $output .= implode("\t",array_keys($trans))."\n"; $output .= "TRNS\t"; $output .= implode("\t",array_values($trans))."\n"; $spl = 0; foreach ($items as $detail) { if (! $spl) { $output .= "!SPL\tSPLID\t"; $output .= implode("\t",array_keys($detail))."\n"; } $output .= sprintf("SPL\t%s\t%s\n",$spl++,implode("\t",array_values($detail))); } $output .= "ENDTRNS\n"; return $output; } /** * Export a payment */ private function payment(Model_Payment $po) { $defaults = array( 'CLEAR'=>'N', 'TRNSTYPE'=>'PAYMENT', ); $payment = $items = array(); $payment['AMOUNT'] = sprintf('%3.2f',$po->total_amt); $payment['TRNSID'] = sprintf('P%06s',$po->id); $payment['DATE'] = date('m/d/Y',$po->date_payment); $payment['NAME'] = $po->account->company ? $po->account->company : sprintf('%s %s',$po->account->last_name,$po->account->first_name); $payment['MEMO'] = sprintf('Payment for invoice(s) %s (%s)',$po->invoicelist(),$po->checkout->name); // @todo Accounts/Payment should be configurable switch ($po->checkout->plugin) { // @todo this is direct debit case 'DD_EZYPAY': $payment['PAYMETH'] = 'DirectDebit'; $payment['ACCNT'] = 'Ezypay'; break; case 'REMIT_CHEQUE': $payment['PAYMETH'] = 'Cheque'; $payment['ACCNT'] = 'Undeposited Funds'; break; case 'REMIT_BANK_WIRE': $payment['PAYMETH'] = 'DirectCredit'; $payment['ACCNT'] = 'Bendigo Bank'; break; case 'PAYPAL_CART': $payment['PAYMETH'] = 'Paypal'; $payment['ACCNT'] = 'Paypal'; break; default: $payment['PAYMETH'] = 'TBA'; $payment['ACCNT'] = 'Undeposited Funds'; } $items[0]['TRANSTYPE'] = 'PAYMENT'; $items[0]['CLEAR'] = 'N'; $items[0]['ACCNT'] = 'Accounts Receivable'; $items[0]['AMOUNT'] = $po->total(); return $this->output(Arr::merge($defaults,$payment),$items); } /** * Export selected invoices */ private function payments(array $ids) { $output = ''; foreach ($ids as $id) $output .= $this->payment(ORM::factory('Payment',$id)); // If all went OK, update our export status $this->update($ids); return $output; } private function update(array $ids) { foreach ($ids as $id) { // Check if we have exported this item already $eio = ORM::factory('Export_Item') ->where('item_id','=',$id) ->and_where('export_module_id','=',$this->emo->id) ->find(); if (! $eio->loaded()) { $eio->item_id = $id; $eio->export_module_id = $this->emo->id; } $eio->save(); } } } ?>