00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 class Mage_Sales_Model_Order_Invoice extends Mage_Sales_Model_Abstract
00029 {
00030
00031
00032
00033 const STATE_OPEN = 1;
00034 const STATE_PAID = 2;
00035 const STATE_CANCELED = 3;
00036
00037 const CAPTURE_ONLINE = 'online';
00038 const CAPTURE_OFFLINE = 'offline';
00039 const NOT_CAPTURE = 'not_capture';
00040
00041 const XML_PATH_EMAIL_TEMPLATE = 'sales_email/invoice/template';
00042 const XML_PATH_EMAIL_GUEST_TEMPLATE = 'sales_email/invoice/guest_template';
00043 const XML_PATH_EMAIL_IDENTITY = 'sales_email/invoice/identity';
00044 const XML_PATH_EMAIL_COPY_TO = 'sales_email/invoice/copy_to';
00045 const XML_PATH_EMAIL_COPY_METHOD = 'sales_email/invoice/copy_method';
00046 const XML_PATH_EMAIL_ENABLED = 'sales_email/invoice/enabled';
00047
00048 const XML_PATH_UPDATE_EMAIL_TEMPLATE = 'sales_email/invoice_comment/template';
00049 const XML_PATH_UPDATE_EMAIL_GUEST_TEMPLATE = 'sales_email/invoice_comment/guest_template';
00050 const XML_PATH_UPDATE_EMAIL_IDENTITY = 'sales_email/invoice_comment/identity';
00051 const XML_PATH_UPDATE_EMAIL_COPY_TO = 'sales_email/invoice_comment/copy_to';
00052 const XML_PATH_UPDATE_EMAIL_COPY_METHOD = 'sales_email/invoice_comment/copy_method';
00053 const XML_PATH_UPDATE_EMAIL_ENABLED = 'sales_email/invoice_comment/enabled';
00054
00055 protected static $_states;
00056
00057 protected $_items;
00058 protected $_comments;
00059 protected $_order;
00060
00061 protected $_saveBeforeDestruct = false;
00062
00063 protected $_eventPrefix = 'sales_order_invoice';
00064 protected $_eventObject = 'invoice';
00065
00066 public function __destruct()
00067 {
00068 if ($this->_saveBeforeDestruct) {
00069 $this->save();
00070 }
00071 }
00072
00073
00074
00075
00076 protected function _construct()
00077 {
00078 $this->_init('sales/order_invoice');
00079 }
00080
00081
00082
00083
00084
00085
00086
00087 public function loadByIncrementId($incrementId)
00088 {
00089 $ids = $this->getCollection()
00090 ->addAttributeToFilter('increment_id', $incrementId)
00091 ->getAllIds();
00092
00093 if (!empty($ids)) {
00094 reset($ids);
00095 $this->load(current($ids));
00096 }
00097 return $this;
00098 }
00099
00100
00101
00102
00103
00104
00105 public function getConfig()
00106 {
00107 return Mage::getSingleton('sales/order_invoice_config');
00108 }
00109
00110
00111
00112
00113
00114
00115 public function getStore()
00116 {
00117 return $this->getOrder()->getStore();
00118 }
00119
00120
00121
00122
00123
00124
00125
00126 public function setOrder(Mage_Sales_Model_Order $order)
00127 {
00128 $this->_order = $order;
00129 $this->setOrderId($order->getId())
00130 ->setStoreId($order->getStoreId());
00131 return $this;
00132 }
00133
00134
00135
00136
00137
00138
00139 public function getOrder()
00140 {
00141 if (!$this->_order instanceof Mage_Sales_Model_Order) {
00142 $this->_order = Mage::getModel('sales/order')->load($this->getOrderId());
00143 }
00144 return $this->_order;
00145 }
00146
00147
00148
00149
00150
00151
00152 public function getBillingAddress()
00153 {
00154 return $this->getOrder()->getBillingAddress();
00155 }
00156
00157
00158
00159
00160
00161
00162 public function getShippingAddress()
00163 {
00164 return $this->getOrder()->getShippingAddress();
00165 }
00166
00167
00168
00169
00170
00171
00172 public function isCanceled()
00173 {
00174 return $this->getState() == self::STATE_CANCELED;
00175 }
00176
00177
00178
00179
00180
00181
00182 public function canCapture()
00183 {
00184 if ($this->getState() != self::STATE_CANCELED &&
00185 $this->getState() != self::STATE_PAID &&
00186 $this->getOrder()->getPayment()->canCapture()) {
00187 return true;
00188 }
00189 return false;
00190 }
00191
00192
00193
00194
00195
00196
00197 public function canVoid()
00198 {
00199 $canVoid = false;
00200 if ($this->getState() == self::STATE_PAID) {
00201 $canVoid = $this->getCanVoidFlag();
00202
00203
00204
00205 if (is_null($canVoid)) {
00206 $canVoid = $this->getOrder()->getPayment()->canVoid($this);
00207 if ($canVoid === false) {
00208 $this->setCanVoidFlag(false);
00209 $this->_saveBeforeDestruct = true;
00210 }
00211 }
00212 else {
00213 $canVoid = (bool) $canVoid;
00214 }
00215 }
00216 return $canVoid;
00217 }
00218
00219
00220
00221
00222
00223
00224 public function canCancel()
00225 {
00226 return $this->getState() == self::STATE_OPEN;
00227 }
00228
00229
00230
00231
00232
00233
00234 public function capture()
00235 {
00236 $this->getOrder()->getPayment()->capture($this);
00237 $this->pay();
00238 return $this;
00239 }
00240
00241
00242
00243
00244
00245
00246 public function pay()
00247 {
00248 $invoiceState = self::STATE_PAID;
00249 if ($this->getOrder()->getPayment()->hasForcedState()) {
00250 $invoiceState = $this->getOrder()->getPayment()->getForcedState();
00251 }
00252
00253 $this->setState($invoiceState);
00254
00255 $this->getOrder()->getPayment()->pay($this);
00256 $this->getOrder()->setTotalPaid(
00257 $this->getOrder()->getTotalPaid()+$this->getGrandTotal()
00258 );
00259 $this->getOrder()->setBaseTotalPaid(
00260 $this->getOrder()->getBaseTotalPaid()+$this->getBaseGrandTotal()
00261 );
00262 Mage::dispatchEvent('sales_order_invoice_pay', array($this->_eventObject=>$this));
00263 return $this;
00264 }
00265
00266
00267
00268
00269
00270
00271 public function void()
00272 {
00273 $this->getOrder()->getPayment()->void($this);
00274 $this->cancel();
00275 return $this;
00276 }
00277
00278
00279
00280
00281
00282
00283 public function cancel()
00284 {
00285 $this->getOrder()->getPayment()->cancelInvoice($this);
00286 foreach ($this->getAllItems() as $item) {
00287 $item->cancel();
00288 }
00289
00290
00291
00292
00293 if ($this->getState() == self::STATE_PAID) {
00294 $this->getOrder()->setTotalPaid(
00295 $this->getOrder()->getTotalPaid()-$this->getGrandTotal()
00296 );
00297 $this->getOrder()->setBaseTotalPaid(
00298 $this->getOrder()->getBaseTotalPaid()-$this->getBaseGrandTotal()
00299 );
00300
00301 $this->getOrder()->setTotalInvoiced(
00302 $this->getOrder()->getTotalInvoiced()-$this->getGrandTotal()
00303 );
00304 $this->getOrder()->setBaseTotalInvoiced(
00305 $this->getOrder()->getBaseTotalInvoiced()-$this->getBaseGrandTotal()
00306 );
00307 }
00308 $this->setState(self::STATE_CANCELED);
00309 $this->getOrder()->setState(Mage_Sales_Model_Order::STATE_PROCESSING, true);
00310 Mage::dispatchEvent('sales_order_invoice_cancel', array($this->_eventObject=>$this));
00311 return $this;
00312 }
00313
00314
00315
00316
00317
00318
00319 public function collectTotals()
00320 {
00321 foreach ($this->getConfig()->getTotalModels() as $model) {
00322 $model->collect($this);
00323 }
00324 return $this;
00325 }
00326
00327 public function getItemsCollection()
00328 {
00329 if (empty($this->_items)) {
00330 $this->_items = Mage::getResourceModel('sales/order_invoice_item_collection')
00331 ->addAttributeToSelect('*')
00332 ->setInvoiceFilter($this->getId());
00333
00334 if ($this->getId()) {
00335 foreach ($this->_items as $item) {
00336 $item->setInvoice($this);
00337 }
00338 }
00339 }
00340 return $this->_items;
00341 }
00342
00343 public function getAllItems()
00344 {
00345 $items = array();
00346 foreach ($this->getItemsCollection() as $item) {
00347 if (!$item->isDeleted()) {
00348 $items[] = $item;
00349 }
00350 }
00351 return $items;
00352 }
00353
00354 public function getItemById($itemId)
00355 {
00356 foreach ($this->getItemsCollection() as $item) {
00357 if ($item->getId()==$itemId) {
00358 return $item;
00359 }
00360 }
00361 return false;
00362 }
00363
00364 public function addItem(Mage_Sales_Model_Order_Invoice_Item $item)
00365 {
00366 $item->setInvoice($this)
00367 ->setParentId($this->getId())
00368 ->setStoreId($this->getStoreId());
00369
00370 if (!$item->getId()) {
00371 $this->getItemsCollection()->addItem($item);
00372 }
00373 return $this;
00374 }
00375
00376
00377
00378
00379
00380
00381 public static function getStates()
00382 {
00383 if (is_null(self::$_states)) {
00384 self::$_states = array(
00385 self::STATE_OPEN => Mage::helper('sales')->__('Pending'),
00386 self::STATE_PAID => Mage::helper('sales')->__('Paid'),
00387 self::STATE_CANCELED => Mage::helper('sales')->__('Canceled'),
00388 );
00389 }
00390 return self::$_states;
00391 }
00392
00393
00394
00395
00396
00397
00398
00399 public function getStateName($stateId = null)
00400 {
00401 if (is_null($stateId)) {
00402 $stateId = $this->getState();
00403 }
00404
00405 if (is_null(self::$_states)) {
00406 self::getStates();
00407 }
00408 if (isset(self::$_states[$stateId])) {
00409 return self::$_states[$stateId];
00410 }
00411 return Mage::helper('sales')->__('Unknown State');
00412 }
00413
00414
00415
00416
00417
00418
00419
00420
00421 public function register()
00422 {
00423 if ($this->getId()) {
00424 Mage::throwException(
00425 Mage::helper('sales')->__('Can not register existing invoice')
00426 );
00427 }
00428
00429 foreach ($this->getAllItems() as $item) {
00430 if ($item->getQty()>0) {
00431 $item->register();
00432 }
00433 else {
00434 $item->isDeleted(true);
00435 }
00436 }
00437
00438 if ($this->canCapture()) {
00439 if ($captureCase = $this->getRequestedCaptureCase()) {
00440 if ($captureCase == self::CAPTURE_ONLINE) {
00441 $this->capture();
00442 }
00443 elseif ($captureCase == self::CAPTURE_OFFLINE) {
00444 $this->setCanVoidFlag(false);
00445 $this->pay();
00446 }
00447 }
00448 }
00449 elseif(!$this->getOrder()->getPayment()->getMethodInstance()->isGateway()) {
00450 $this->pay();
00451 }
00452
00453 $this->getOrder()->setTotalInvoiced(
00454 $this->getOrder()->getTotalInvoiced()+$this->getGrandTotal()
00455 );
00456 $this->getOrder()->setBaseTotalInvoiced(
00457 $this->getOrder()->getBaseTotalInvoiced()+$this->getBaseGrandTotal()
00458 );
00459
00460 $this->getOrder()->setSubtotalInvoiced(
00461 $this->getOrder()->getSubtotalInvoiced()+$this->getSubtotal()
00462 );
00463 $this->getOrder()->setBaseSubtotalInvoiced(
00464 $this->getOrder()->getBaseSubtotalInvoiced()+$this->getBaseSubtotal()
00465 );
00466
00467 $this->getOrder()->setTaxInvoiced(
00468 $this->getOrder()->getTaxInvoiced()+$this->getTaxAmount()
00469 );
00470 $this->getOrder()->setBaseTaxInvoiced(
00471 $this->getOrder()->getBaseTaxInvoiced()+$this->getBaseTaxAmount()
00472 );
00473
00474 $this->getOrder()->setShippingInvoiced(
00475 $this->getOrder()->getShippingInvoiced()+$this->getShippingAmount()
00476 );
00477 $this->getOrder()->setBaseShippingInvoiced(
00478 $this->getOrder()->getBaseShippingInvoiced()+$this->getBaseShippingAmount()
00479 );
00480
00481 $this->getOrder()->setDiscountInvoiced(
00482 $this->getOrder()->getDiscountInvoiced()+$this->getDiscountAmount()
00483 );
00484 $this->getOrder()->setBaseDiscountInvoiced(
00485 $this->getOrder()->getBaseDiscountInvoiced()+$this->getBaseDiscountAmount()
00486 );
00487
00488 $state = $this->getState();
00489 if (is_null($state)) {
00490 $this->setState(self::STATE_OPEN);
00491 }
00492 return $this;
00493 }
00494
00495
00496
00497
00498
00499
00500 public function isLast()
00501 {
00502 foreach ($this->getAllItems() as $item) {
00503 if (!$item->isLast()) {
00504 return false;
00505 }
00506 }
00507 return true;
00508 }
00509
00510 public function addComment($comment, $notify=false)
00511 {
00512 if (!($comment instanceof Mage_Sales_Model_Order_Invoice_Comment)) {
00513 $comment = Mage::getModel('sales/order_invoice_comment')
00514 ->setComment($comment)
00515 ->setIsCustomerNotified($notify);
00516 }
00517 $comment->setInvoice($this)
00518 ->setStoreId($this->getStoreId())
00519 ->setParentId($this->getId());
00520 if (!$comment->getId()) {
00521 $this->getCommentsCollection()->addItem($comment);
00522 }
00523 return $this;
00524 }
00525
00526 public function getCommentsCollection($reload=false)
00527 {
00528 if (is_null($this->_comments) || $reload) {
00529 $this->_comments = Mage::getResourceModel('sales/order_invoice_comment_collection')
00530 ->addAttributeToSelect('*')
00531 ->setInvoiceFilter($this->getId())
00532 ->setCreatedAtOrder();
00533 if ($this->getId()) {
00534 foreach ($this->_comments as $comment) {
00535 $comment->setInvoice($this);
00536 }
00537 }
00538 }
00539 return $this->_comments;
00540 }
00541
00542
00543
00544
00545
00546
00547 public function sendEmail($notifyCustomer=true, $comment='')
00548 {
00549 if (!Mage::helper('sales')->canSendNewInvoiceEmail($this->getOrder()->getStore()->getId())) {
00550 return $this;
00551 }
00552
00553 $currentDesign = Mage::getDesign()->setAllGetOld(array(
00554 'package' => Mage::getStoreConfig('design/package/name', $this->getStoreId()),
00555 'store' => $this->getStoreId()
00556 ));
00557
00558 $translate = Mage::getSingleton('core/translate');
00559
00560 $translate->setTranslateInline(false);
00561
00562 $order = $this->getOrder();
00563 $copyTo = $this->_getEmails(self::XML_PATH_EMAIL_COPY_TO);
00564 $copyMethod = Mage::getStoreConfig(self::XML_PATH_EMAIL_COPY_METHOD, $this->getStoreId());
00565
00566 if (!$notifyCustomer && !$copyTo) {
00567 return $this;
00568 }
00569 $paymentBlock = Mage::helper('payment')->getInfoBlock($order->getPayment())
00570 ->setIsSecureMode(true);
00571
00572 $mailTemplate = Mage::getModel('core/email_template');
00573
00574 if ($order->getCustomerIsGuest()) {
00575 $template = Mage::getStoreConfig(self::XML_PATH_EMAIL_GUEST_TEMPLATE, $order->getStoreId());
00576 $customerName = $order->getBillingAddress()->getName();
00577 } else {
00578 $template = Mage::getStoreConfig(self::XML_PATH_EMAIL_TEMPLATE, $order->getStoreId());
00579 $customerName = $order->getCustomerName();
00580 }
00581
00582 if ($notifyCustomer) {
00583 $sendTo[] = array(
00584 'name' => $customerName,
00585 'email' => $order->getCustomerEmail()
00586 );
00587 if ($copyTo && $copyMethod == 'bcc') {
00588 foreach ($copyTo as $email) {
00589 $mailTemplate->addBcc($email);
00590 }
00591 }
00592
00593 }
00594
00595 if ($copyTo && ($copyMethod == 'copy' || !$notifyCustomer)) {
00596 foreach ($copyTo as $email) {
00597 $sendTo[] = array(
00598 'name' => null,
00599 'email' => $email
00600 );
00601 }
00602 }
00603
00604 foreach ($sendTo as $recipient) {
00605 $mailTemplate->setDesignConfig(array('area'=>'frontend', 'store'=>$order->getStoreId()))
00606 ->sendTransactional(
00607 $template,
00608 Mage::getStoreConfig(self::XML_PATH_EMAIL_IDENTITY, $order->getStoreId()),
00609 $recipient['email'],
00610 $recipient['name'],
00611 array(
00612 'order' => $order,
00613 'invoice' => $this,
00614 'comment' => $comment,
00615 'billing' => $order->getBillingAddress(),
00616 'payment_html'=> $paymentBlock->toHtml(),
00617 )
00618 );
00619 }
00620
00621 $translate->setTranslateInline(true);
00622
00623 Mage::getDesign()->setAllGetOld($currentDesign);
00624
00625 return $this;
00626 }
00627
00628
00629
00630
00631
00632
00633 public function sendUpdateEmail($notifyCustomer=true, $comment='')
00634 {
00635 if (!Mage::helper('sales')->canSendInvoiceCommentEmail($this->getOrder()->getStore()->getId())) {
00636 return $this;
00637 }
00638
00639 $currentDesign = Mage::getDesign()->setAllGetOld(array(
00640 'package' => Mage::getStoreConfig('design/package/name', $this->getStoreId()),
00641 ));
00642
00643 $translate = Mage::getSingleton('core/translate');
00644
00645 $translate->setTranslateInline(false);
00646
00647 $order = $this->getOrder();
00648
00649 $copyTo = $this->_getEmails(self::XML_PATH_UPDATE_EMAIL_COPY_TO);
00650 $copyMethod = Mage::getStoreConfig(self::XML_PATH_UPDATE_EMAIL_COPY_METHOD, $this->getStoreId());
00651
00652 if (!$notifyCustomer && !$copyTo) {
00653 return $this;
00654 }
00655
00656 $sendTo = array();
00657
00658 $mailTemplate = Mage::getModel('core/email_template');
00659
00660 if ($order->getCustomerIsGuest()) {
00661 $template = Mage::getStoreConfig(self::XML_PATH_UPDATE_EMAIL_GUEST_TEMPLATE, $order->getStoreId());
00662 $customerName = $order->getBillingAddress()->getName();
00663 } else {
00664 $template = Mage::getStoreConfig(self::XML_PATH_UPDATE_EMAIL_TEMPLATE, $order->getStoreId());
00665 $customerName = $order->getCustomerName();
00666 }
00667
00668 if ($notifyCustomer) {
00669 $sendTo[] = array(
00670 'name' => $customerName,
00671 'email' => $order->getCustomerEmail()
00672 );
00673 if ($copyTo && $copyMethod == 'bcc') {
00674 foreach ($copyTo as $email) {
00675 $mailTemplate->addBcc($email);
00676 }
00677 }
00678
00679 }
00680
00681 if ($copyTo && ($copyMethod == 'copy' || !$notifyCustomer)) {
00682 foreach ($copyTo as $email) {
00683 $sendTo[] = array(
00684 'name' => null,
00685 'email' => $email
00686 );
00687 }
00688 }
00689
00690 foreach ($sendTo as $recipient) {
00691 $mailTemplate->setDesignConfig(array('area'=>'frontend', 'store'=>$order->getStoreId()))
00692 ->sendTransactional(
00693 $template,
00694 Mage::getStoreConfig(self::XML_PATH_UPDATE_EMAIL_IDENTITY, $order->getStoreId()),
00695 $recipient['email'],
00696 $recipient['name'],
00697 array(
00698 'order' => $order,
00699 'billing'=> $order->getBillingAddress(),
00700 'invoice'=> $this,
00701 'comment'=> $comment
00702 )
00703 );
00704 }
00705
00706 $translate->setTranslateInline(true);
00707
00708 Mage::getDesign()->setAllGetOld($currentDesign);
00709
00710 return $this;
00711 }
00712
00713 protected function _getEmails($configPath)
00714 {
00715 $data = Mage::getStoreConfig($configPath, $this->getStoreId());
00716 if (!empty($data)) {
00717 return explode(',', $data);
00718 }
00719 return false;
00720 }
00721
00722 protected function _beforeDelete()
00723 {
00724 $this->_protectFromNonAdmin();
00725 return parent::_beforeDelete();
00726 }
00727 }