Version Notes
Initial release.
Download this release
Release Info
Developer | Hussey Coding |
Extension | HusseyCoding_Backorder |
Version | 1.0.1 |
Comparing to | |
See all releases |
Version 1.0.1
- app/code/community/HusseyCoding/Backorder/Block/Estimate.php +254 -0
- app/code/community/HusseyCoding/Backorder/Helper/Data.php +225 -0
- app/code/community/HusseyCoding/Backorder/Model/Observer.php +28 -0
- app/code/community/HusseyCoding/Backorder/Model/Order/SalesItem.php +23 -0
- app/code/community/HusseyCoding/Backorder/controllers/IndexController.php +17 -0
- app/code/community/HusseyCoding/Backorder/etc/adminhtml.xml +25 -0
- app/code/community/HusseyCoding/Backorder/etc/config.xml +74 -0
- app/code/community/HusseyCoding/Backorder/etc/system.xml +102 -0
- app/code/community/HusseyCoding/Backorder/sql/backorder_setup/install-1.0.0.php +18 -0
- app/code/community/HusseyCoding/Backorder/sql/backorder_setup/upgrade-1.0.0-1.0.1.php +7 -0
- app/code/community/HusseyCoding/Common/etc/system.xml +9 -0
- app/design/frontend/base/default/layout/backorder.xml +22 -0
- app/design/frontend/base/default/template/backorder/estimate.phtml +75 -0
- app/etc/modules/HusseyCoding_Backorder.xml +9 -0
- app/etc/modules/HusseyCoding_Common.xml +9 -0
- package.xml +18 -0
- skin/frontend/base/default/css/backorder.css +3 -0
- skin/frontend/base/default/js/backorder.js +211 -0
app/code/community/HusseyCoding/Backorder/Block/Estimate.php
ADDED
@@ -0,0 +1,254 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class HusseyCoding_Backorder_Block_Estimate extends Mage_Core_Block_Template
|
3 |
+
{
|
4 |
+
private $_ids = array();
|
5 |
+
private $_product;
|
6 |
+
private $_typeid;
|
7 |
+
private $_childids = array();
|
8 |
+
private $_bundleids = array();
|
9 |
+
|
10 |
+
public function isEnabled()
|
11 |
+
{
|
12 |
+
return Mage::helper('backorder')->isEnabled();
|
13 |
+
}
|
14 |
+
|
15 |
+
public function acceptEnabled()
|
16 |
+
{
|
17 |
+
if (Mage::helper('backorder')->acceptEnabled()):
|
18 |
+
return 'true';
|
19 |
+
endif;
|
20 |
+
|
21 |
+
return 'false';
|
22 |
+
}
|
23 |
+
|
24 |
+
public function getProductEstimate()
|
25 |
+
{
|
26 |
+
if ($this->_getProductType() == 'grouped'):
|
27 |
+
return $this->_getGroupedEstimates($this->_getProduct());
|
28 |
+
elseif ($this->_getProductType() == 'configurable'):
|
29 |
+
return $this->_getConfigurableEstimates($this->_getProduct());
|
30 |
+
elseif ($this->_getProductType() == 'bundle'):
|
31 |
+
return $this->_getBundleEstimates($this->_getProduct());
|
32 |
+
endif;
|
33 |
+
|
34 |
+
return $this->_getEstimateDate($this->_getProduct());
|
35 |
+
}
|
36 |
+
|
37 |
+
private function _getProduct()
|
38 |
+
{
|
39 |
+
if (!isset($this->_product)):
|
40 |
+
$this->_product = Mage::registry('current_product');
|
41 |
+
endif;
|
42 |
+
|
43 |
+
return $this->_product;
|
44 |
+
}
|
45 |
+
|
46 |
+
private function _getProductType()
|
47 |
+
{
|
48 |
+
if (!isset($this->_typeid)):
|
49 |
+
$this->_typeid = $this->_getProduct()->getTypeId();
|
50 |
+
endif;
|
51 |
+
|
52 |
+
return $this->_typeid;
|
53 |
+
}
|
54 |
+
|
55 |
+
public function getProductType()
|
56 |
+
{
|
57 |
+
return $this->_getProductType();
|
58 |
+
}
|
59 |
+
|
60 |
+
private function _getGroupedEstimates($product)
|
61 |
+
{
|
62 |
+
$ids = Mage::getModel('catalog/product_type_grouped')->getChildrenIds($product->getId());
|
63 |
+
|
64 |
+
return $this->_getEstimatesByIds($ids);
|
65 |
+
}
|
66 |
+
|
67 |
+
private function _getConfigurableEstimates($product)
|
68 |
+
{
|
69 |
+
$ids = Mage::getModel('catalog/product_type_configurable')->getChildrenIds($product->getId());
|
70 |
+
|
71 |
+
return $this->_getEstimatesByIds($ids);
|
72 |
+
}
|
73 |
+
|
74 |
+
private function _getBundleEstimates($product)
|
75 |
+
{
|
76 |
+
$estimates = array();
|
77 |
+
$optionCollection = $product->getTypeInstance(true)->getOptionsCollection($product);
|
78 |
+
$selectionCollection = $product->getTypeInstance(true)->getSelectionsCollection(
|
79 |
+
$product->getTypeInstance(true)->getOptionsIds($product),
|
80 |
+
$product
|
81 |
+
);
|
82 |
+
|
83 |
+
$options = $optionCollection->appendSelections($selectionCollection);
|
84 |
+
foreach ($options as $option):
|
85 |
+
if ($selections = $option->getSelections()):
|
86 |
+
$optionid = $option->getId();
|
87 |
+
foreach ($selections as $selection):
|
88 |
+
$selectionid = $selection->getSelectionId();
|
89 |
+
$simpleproduct = Mage::getModel('catalog/product')->load($selection->getId());
|
90 |
+
if ($estimate = $this->_getEstimateDate($simpleproduct)):
|
91 |
+
$estimates[$optionid][$selectionid]['estimate'] = $estimate;
|
92 |
+
$estimates[$optionid][$selectionid]['epoch'] = strtotime($estimate);
|
93 |
+
endif;
|
94 |
+
endforeach;
|
95 |
+
endif;
|
96 |
+
endforeach;
|
97 |
+
|
98 |
+
if (!empty($estimates)):
|
99 |
+
return $estimates;
|
100 |
+
endif;
|
101 |
+
|
102 |
+
return false;
|
103 |
+
}
|
104 |
+
|
105 |
+
private function _getEstimatesByIds($ids)
|
106 |
+
{
|
107 |
+
foreach ($ids as $group):
|
108 |
+
foreach ($group as $id):
|
109 |
+
$product = Mage::getModel('catalog/product')->load($id);
|
110 |
+
$estimate = $this->_getEstimateDate($product);
|
111 |
+
if ($estimate):
|
112 |
+
$estimates[$product->getId()] = $estimate;
|
113 |
+
endif;
|
114 |
+
endforeach;
|
115 |
+
endforeach;
|
116 |
+
|
117 |
+
if (!empty($estimates)):
|
118 |
+
return $estimates;
|
119 |
+
endif;
|
120 |
+
|
121 |
+
return false;
|
122 |
+
}
|
123 |
+
|
124 |
+
private function _getEstimateDate($product)
|
125 |
+
{
|
126 |
+
return Mage::helper('backorder')->getEstimatedDispatch($product);
|
127 |
+
}
|
128 |
+
|
129 |
+
public function getCartEstimates()
|
130 |
+
{
|
131 |
+
$return = array();
|
132 |
+
if ($cart = Mage::getModel('checkout/cart')->getQuote()):
|
133 |
+
$empty = true;
|
134 |
+
foreach ($cart->getAllItems() as $item):
|
135 |
+
if ($parent = $item->getParentItemId()):
|
136 |
+
$this->_childids[$parent][] = $item;
|
137 |
+
else:
|
138 |
+
$this->_ids[] = $item->getId();
|
139 |
+
if ($item->getProductType() == 'configurable'):
|
140 |
+
if ($option = $item->getOptionByCode('simple_product')):
|
141 |
+
if ($estimate = $this->_getEstimateDate($option->getProduct())):
|
142 |
+
$return[] = $estimate;
|
143 |
+
$empty = false;
|
144 |
+
else:
|
145 |
+
$return[] = '';
|
146 |
+
endif;
|
147 |
+
endif;
|
148 |
+
elseif ($item->getProductType() == 'bundle'):
|
149 |
+
$options = $item->getProduct()->getTypeInstance(true)->getOrderOptions($item->getProduct());
|
150 |
+
$bundleid = $item->getId();
|
151 |
+
$this->_bundleids[] = $bundleid;
|
152 |
+
$return[$bundleid] = '';
|
153 |
+
$empty = false;
|
154 |
+
else:
|
155 |
+
if ($estimate = $this->_getEstimateDate($item->getProduct())):
|
156 |
+
$return[] = $estimate;
|
157 |
+
$empty = false;
|
158 |
+
else:
|
159 |
+
$return[] = '';
|
160 |
+
endif;
|
161 |
+
endif;
|
162 |
+
endif;
|
163 |
+
endforeach;
|
164 |
+
|
165 |
+
foreach ($this->_bundleids as $bundleid):
|
166 |
+
$estimates = array();
|
167 |
+
if (isset($this->_childids[$bundleid])):
|
168 |
+
foreach ($this->_childids[$bundleid] as $childitem):
|
169 |
+
if ($estimate = $this->_getEstimateDate($childitem->getProduct())):
|
170 |
+
$epoch = strtotime($estimate);
|
171 |
+
$estimates[$epoch] = $estimate;
|
172 |
+
endif;
|
173 |
+
endforeach;
|
174 |
+
if (!empty($estimates)):
|
175 |
+
ksort($estimates);
|
176 |
+
$return[$bundleid] = end($estimates);
|
177 |
+
endif;
|
178 |
+
endif;
|
179 |
+
endforeach;
|
180 |
+
|
181 |
+
if (!$empty):
|
182 |
+
return '["' . implode('","', $return) . '"]';
|
183 |
+
endif;
|
184 |
+
endif;
|
185 |
+
|
186 |
+
return '[]';
|
187 |
+
}
|
188 |
+
|
189 |
+
public function getItemIds()
|
190 |
+
{
|
191 |
+
if (!empty($this->_ids)):
|
192 |
+
return '["' . implode('","', $this->_ids) . '"]';
|
193 |
+
endif;
|
194 |
+
|
195 |
+
return '[]';
|
196 |
+
}
|
197 |
+
|
198 |
+
public function getHasAccepted()
|
199 |
+
{
|
200 |
+
if (Mage::getSingleton('customer/session')->getBackorderAccepted()):
|
201 |
+
return 'true';
|
202 |
+
endif;
|
203 |
+
|
204 |
+
return 'false';
|
205 |
+
}
|
206 |
+
|
207 |
+
public function getAcceptedIds()
|
208 |
+
{
|
209 |
+
if ($ids = Mage::getSingleton('customer/session')->getBackorderAcceptedIds()):
|
210 |
+
return '["' . implode('","', $ids) . '"]';
|
211 |
+
endif;
|
212 |
+
|
213 |
+
return '[]';
|
214 |
+
}
|
215 |
+
|
216 |
+
public function isProduct()
|
217 |
+
{
|
218 |
+
if (Mage::registry('current_product')):
|
219 |
+
return 'true';
|
220 |
+
endif;
|
221 |
+
|
222 |
+
return 'false';
|
223 |
+
}
|
224 |
+
|
225 |
+
public function isCart()
|
226 |
+
{
|
227 |
+
$request = Mage::app()->getRequest();
|
228 |
+
$module = $request->getModuleName();
|
229 |
+
$controller = $request->getControllerName();
|
230 |
+
$action = $request->getActionName();
|
231 |
+
if ($module == 'checkout' && $controller = 'cart' && $action = 'index'):
|
232 |
+
return 'true';
|
233 |
+
endif;
|
234 |
+
|
235 |
+
return 'false';
|
236 |
+
}
|
237 |
+
|
238 |
+
public function getCutOff()
|
239 |
+
{
|
240 |
+
$cutoff = Mage::helper('backorder')->getCutOff();
|
241 |
+
$return = strtotime($cutoff);
|
242 |
+
$now = Mage::getModel('core/date')->timestamp();
|
243 |
+
if ($now >= $return):
|
244 |
+
$return = strtotime('tomorrow ' . $cutoff);
|
245 |
+
endif;
|
246 |
+
|
247 |
+
return $return;
|
248 |
+
}
|
249 |
+
|
250 |
+
public function getOrderBefore()
|
251 |
+
{
|
252 |
+
return Mage::helper('backorder')->getOrderBefore();
|
253 |
+
}
|
254 |
+
}
|
app/code/community/HusseyCoding/Backorder/Helper/Data.php
ADDED
@@ -0,0 +1,225 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class HusseyCoding_Backorder_Helper_Data extends Mage_Core_Helper_Abstract
|
3 |
+
{
|
4 |
+
private $_dashcount;
|
5 |
+
|
6 |
+
public function isEnabled()
|
7 |
+
{
|
8 |
+
return Mage::getStoreConfig('backorder/general/enabled');
|
9 |
+
}
|
10 |
+
|
11 |
+
public function acceptEnabled()
|
12 |
+
{
|
13 |
+
return Mage::getStoreConfig('backorder/general/agreement');
|
14 |
+
}
|
15 |
+
|
16 |
+
public function hasAccepted()
|
17 |
+
{
|
18 |
+
$needsaccept = false;
|
19 |
+
if ($cart = Mage::getModel('checkout/cart')->getQuote()):
|
20 |
+
foreach ($cart->getAllItems() as $item):
|
21 |
+
$product = Mage::getModel('catalog/product')->load($item->getProduct()->getId());
|
22 |
+
if ($product->getBackorder()):
|
23 |
+
$needsaccept = true;
|
24 |
+
break;
|
25 |
+
endif;
|
26 |
+
endforeach;
|
27 |
+
endif;
|
28 |
+
|
29 |
+
if ($needsaccept):
|
30 |
+
return Mage::getSingleton('customer/session')->getBackorderAccepted() ? true : false;
|
31 |
+
endif;
|
32 |
+
|
33 |
+
return true;
|
34 |
+
}
|
35 |
+
|
36 |
+
public function getEstimatedDispatch($product)
|
37 |
+
{
|
38 |
+
if (!empty($product) && $product->getId()):
|
39 |
+
$product = Mage::getModel('catalog/product')->load($product->getId());
|
40 |
+
$stock = Mage::getModel('cataloginventory/stock_item')->loadByProduct($product);
|
41 |
+
if ($this->_areManagingStock($stock)):
|
42 |
+
if (!Mage::getStoreConfig('backorder/general/ignorestock')):
|
43 |
+
if ($stock->getQty() > 0 && $stock->getIsInStock()):
|
44 |
+
return false;
|
45 |
+
else:
|
46 |
+
if (!$stock->getBackorders()):
|
47 |
+
return false;
|
48 |
+
endif;
|
49 |
+
endif;
|
50 |
+
endif;
|
51 |
+
else:
|
52 |
+
if (!Mage::getStoreConfig('backorder/general/notmanaged')):
|
53 |
+
return false;
|
54 |
+
endif;
|
55 |
+
endif;
|
56 |
+
$backorder = $product->getBackorder();
|
57 |
+
if (!empty($backorder)):
|
58 |
+
$backorder = str_replace(' and ', ' + ', $backorder);
|
59 |
+
if ($time = strtotime($backorder)):
|
60 |
+
$estimate = new Zend_Date($time, Zend_Date::TIMESTAMP);
|
61 |
+
$digit = $estimate->get(Zend_Date::WEEKDAY_8601);
|
62 |
+
if (($estimate->get(Zend_Date::WEEKDAY_8601) > 5) || ($estimate->isLater($this->_getCutOff(), Zend_Date::TIMES))):
|
63 |
+
$estimate->set(strtotime('+1 weekday', $estimate->toString(Zend_Date::TIMESTAMP)), Zend_Date::TIMESTAMP);
|
64 |
+
endif;
|
65 |
+
$estimate = $this->_setDateAfterHolidays($estimate);
|
66 |
+
$estimate = $estimate->toString(Zend_Date::TIMESTAMP);
|
67 |
+
$estimate = date('l, jS F', $estimate);
|
68 |
+
if (!empty($estimate)):
|
69 |
+
return $estimate;
|
70 |
+
endif;
|
71 |
+
endif;
|
72 |
+
endif;
|
73 |
+
endif;
|
74 |
+
|
75 |
+
return false;
|
76 |
+
}
|
77 |
+
|
78 |
+
private function _areManagingStock($stock)
|
79 |
+
{
|
80 |
+
if ($stock->getUseConfigManageStock()):
|
81 |
+
if (Mage::getStoreConfig(Mage_CatalogInventory_Model_Stock_Item::XML_PATH_ITEM . 'manage_stock')):
|
82 |
+
return true;
|
83 |
+
endif;
|
84 |
+
else:
|
85 |
+
if ($stock->getManageStock()):
|
86 |
+
return true;
|
87 |
+
endif;
|
88 |
+
endif;
|
89 |
+
|
90 |
+
return false;
|
91 |
+
}
|
92 |
+
|
93 |
+
private function _getCutOff()
|
94 |
+
{
|
95 |
+
if ($time = Mage::getStoreConfig('backorder/general/cutoff')):
|
96 |
+
if ($time = strtotime($time)):
|
97 |
+
if ($time = date('H:i:s', $time)):
|
98 |
+
return $time;
|
99 |
+
endif;
|
100 |
+
endif;
|
101 |
+
endif;
|
102 |
+
|
103 |
+
return '17:00:00';
|
104 |
+
}
|
105 |
+
|
106 |
+
public function getCutOff()
|
107 |
+
{
|
108 |
+
return $this->_getCutOff();
|
109 |
+
}
|
110 |
+
|
111 |
+
public function getOrderBefore()
|
112 |
+
{
|
113 |
+
return Mage::getStoreConfig('backorder/general/orderbefore');
|
114 |
+
}
|
115 |
+
|
116 |
+
private function _setDateAfterHolidays($estimate)
|
117 |
+
{
|
118 |
+
$holidays = $this->_getHolidayDates();
|
119 |
+
while (in_array($this->_getCurrent($estimate), $holidays)):
|
120 |
+
$estimate->set(strtotime('+1 weekday', $estimate->toString(Zend_Date::TIMESTAMP)), Zend_Date::TIMESTAMP);
|
121 |
+
endwhile;
|
122 |
+
|
123 |
+
return $estimate;
|
124 |
+
}
|
125 |
+
|
126 |
+
private function _getCurrent($estimate)
|
127 |
+
{
|
128 |
+
$current = $estimate->toString(Zend_Date::TIMESTAMP);
|
129 |
+
return date('Y-m-d', $current);
|
130 |
+
}
|
131 |
+
|
132 |
+
private function _getHolidayDates()
|
133 |
+
{
|
134 |
+
$fixedholidays = $this->_getValidDates(Mage::getStoreConfig('backorder/general/fixed_holidays'), 2);
|
135 |
+
$dynamicholidays = $this->_getValidDates(Mage::getStoreConfig('backorder/general/dynamic_holidays'), 3);
|
136 |
+
|
137 |
+
$thisyear = date('Y', Mage::getModel('core/date')->timestamp());
|
138 |
+
$nextyear = date('Y', strtotime($thisyear . ' +1 year'));
|
139 |
+
$holidays = array();
|
140 |
+
|
141 |
+
foreach ($fixedholidays as $holiday):
|
142 |
+
$holiday = explode('-', $holiday);
|
143 |
+
$holidays[] = strtotime($thisyear . '-' . end($holiday) . '-' . reset($holiday));
|
144 |
+
$holidays[] = strtotime($nextyear . '-' . end($holiday) . '-' . reset($holiday));
|
145 |
+
endforeach;
|
146 |
+
|
147 |
+
foreach ($dynamicholidays as $holiday):
|
148 |
+
$parts = explode('-', $holiday);
|
149 |
+
$day = (int) array_shift($parts);
|
150 |
+
$week = array_shift($parts);
|
151 |
+
$week = ltrim($week, '0');
|
152 |
+
$month = (int) array_shift($parts);
|
153 |
+
|
154 |
+
foreach (array($thisyear, $nextyear) as $year):
|
155 |
+
if ($week == 'last'):
|
156 |
+
$weekcount = 0;
|
157 |
+
$daycount = date('t', mktime(0, 0, 0, $month, 1, $year));
|
158 |
+
for ($i = 1; $i <= $daycount; $i++):
|
159 |
+
$weekday = date('N', mktime(0, 0, 0, $month, $i, $year));
|
160 |
+
if ($weekday == $day):
|
161 |
+
$weekcount++;
|
162 |
+
endif;
|
163 |
+
endfor;
|
164 |
+
$week = $weekcount;
|
165 |
+
endif;
|
166 |
+
|
167 |
+
$earliest = (7 * ($week - 1)) + 1;
|
168 |
+
$weekday = date("N", mktime(0, 0, 0, $month, $earliest, $year));
|
169 |
+
|
170 |
+
if ($day == $weekday):
|
171 |
+
$offset = 0;
|
172 |
+
elseif ($day < $weekday):
|
173 |
+
$offset = $day + (7 - $weekday);
|
174 |
+
else:
|
175 |
+
$offset = ($day + (7 - $weekday)) - 7;
|
176 |
+
endif;
|
177 |
+
|
178 |
+
$date = mktime(0, 0, 0, $month, $earliest + $offset, $year);
|
179 |
+
$holidays[] = $date;
|
180 |
+
endforeach;
|
181 |
+
endforeach;
|
182 |
+
|
183 |
+
$return = array();
|
184 |
+
foreach ($holidays as $date):
|
185 |
+
$return[] = date('Y-m-d', $date);
|
186 |
+
endforeach;
|
187 |
+
|
188 |
+
return $return;
|
189 |
+
}
|
190 |
+
|
191 |
+
private function _getValidDates($config, $dashcount)
|
192 |
+
{
|
193 |
+
if (!empty($config)):
|
194 |
+
$this->_dashcount = $dashcount;
|
195 |
+
$dates = explode(',', $config);
|
196 |
+
$dates = array_filter($dates, array($this, '_validateFormat'));
|
197 |
+
if (!empty($dates)):
|
198 |
+
return $dates;
|
199 |
+
endif;
|
200 |
+
endif;
|
201 |
+
|
202 |
+
return array();
|
203 |
+
}
|
204 |
+
|
205 |
+
private function _validateFormat($date)
|
206 |
+
{
|
207 |
+
$date = trim($date);
|
208 |
+
if (!empty($date)):
|
209 |
+
switch ($this->_dashcount):
|
210 |
+
case 2:
|
211 |
+
if (preg_match('/^[0-9]{1,2}-[0-9]{1,2}$/', $date)):
|
212 |
+
return true;
|
213 |
+
endif;
|
214 |
+
break;
|
215 |
+
case 3:
|
216 |
+
if (preg_match('/^[0-9]{1,2}-[0-9]{1,2}-[0-9]{1,2}$/', $date) || preg_match('/^[0-9]{1,2}-last-[0-9]{1,2}$/', $date)):
|
217 |
+
return true;
|
218 |
+
endif;
|
219 |
+
break;
|
220 |
+
endswitch;
|
221 |
+
endif;
|
222 |
+
|
223 |
+
return false;
|
224 |
+
}
|
225 |
+
}
|
app/code/community/HusseyCoding/Backorder/Model/Observer.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class HusseyCoding_Backorder_Model_Observer
|
3 |
+
{
|
4 |
+
public function frontendControllerActionPredispatchCheckout($observer)
|
5 |
+
{
|
6 |
+
if (Mage::helper('backorder')->isEnabled() && Mage::helper('backorder')->acceptEnabled()):
|
7 |
+
$controller = Mage::app()->getRequest()->getControllerName();
|
8 |
+
if ($controller != 'cart' && $controller != 'index'):
|
9 |
+
$helper = Mage::helper('backorder');
|
10 |
+
if (!$helper->hasAccepted()):
|
11 |
+
$url = Mage::getUrl('checkout/cart');
|
12 |
+
$error = $helper->__('You must accept the estimated product dispatch date(s) to checkout.');
|
13 |
+
Mage::getSingleton('checkout/session')->addError($error);
|
14 |
+
$observer->getControllerAction()->getResponse()->setRedirect($url);
|
15 |
+
endif;
|
16 |
+
endif;
|
17 |
+
endif;
|
18 |
+
}
|
19 |
+
|
20 |
+
public function frontendSalesOrderPlaceAfter($observer)
|
21 |
+
{
|
22 |
+
if (Mage::helper('backorder')->isEnabled() && Mage::helper('backorder')->acceptEnabled()):
|
23 |
+
Mage::getSingleton('customer/session')->setBackorderAccepted(false);
|
24 |
+
Mage::getSingleton('customer/session')->setBackorderAcceptedIds(array());
|
25 |
+
Mage::register('is_backorder_email', true);
|
26 |
+
endif;
|
27 |
+
}
|
28 |
+
}
|
app/code/community/HusseyCoding/Backorder/Model/Order/SalesItem.php
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class HusseyCoding_Backorder_Model_Order_SalesItem extends Mage_Sales_Model_Order_Item
|
3 |
+
{
|
4 |
+
public function getName()
|
5 |
+
{
|
6 |
+
if ($this->_isOrderEmail()):
|
7 |
+
if ($estimate = Mage::helper('backorder')->getEstimatedDispatch($this->getProduct())):
|
8 |
+
return parent::getName() . ' - Estimated dispatch: ' . $estimate;
|
9 |
+
endif;
|
10 |
+
endif;
|
11 |
+
|
12 |
+
return parent::getName();
|
13 |
+
}
|
14 |
+
|
15 |
+
private function _isOrderEmail()
|
16 |
+
{
|
17 |
+
if (Mage::registry('is_backorder_email')):
|
18 |
+
return true;
|
19 |
+
endif;
|
20 |
+
|
21 |
+
return false;
|
22 |
+
}
|
23 |
+
}
|
app/code/community/HusseyCoding/Backorder/controllers/IndexController.php
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class HusseyCoding_Backorder_IndexController extends Mage_Core_Controller_Front_Action
|
3 |
+
{
|
4 |
+
public function indexAction()
|
5 |
+
{
|
6 |
+
$accepted = $this->getRequest()->getPost('accepted');
|
7 |
+
$accepted = !empty($accepted) && $accepted == 'true' ? true : false;
|
8 |
+
|
9 |
+
Mage::getSingleton('customer/session')->setBackorderAccepted($accepted);
|
10 |
+
|
11 |
+
if ($itemids = $this->getRequest()->getPost('itemids')):
|
12 |
+
$itemids = explode(',', $itemids);
|
13 |
+
Mage::getSingleton('customer/session')->setBackorderAcceptedIds($itemids);
|
14 |
+
endif;
|
15 |
+
|
16 |
+
}
|
17 |
+
}
|
app/code/community/HusseyCoding/Backorder/etc/adminhtml.xml
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<acl>
|
4 |
+
<resources>
|
5 |
+
<all>
|
6 |
+
<title>Allow Everything</title>
|
7 |
+
</all>
|
8 |
+
<admin>
|
9 |
+
<children>
|
10 |
+
<system>
|
11 |
+
<children>
|
12 |
+
<config>
|
13 |
+
<children>
|
14 |
+
<backorder module="backorder">
|
15 |
+
<title>Backorder</title>
|
16 |
+
</backorder>
|
17 |
+
</children>
|
18 |
+
</config>
|
19 |
+
</children>
|
20 |
+
</system>
|
21 |
+
</children>
|
22 |
+
</admin>
|
23 |
+
</resources>
|
24 |
+
</acl>
|
25 |
+
</config>
|
app/code/community/HusseyCoding/Backorder/etc/config.xml
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<HusseyCoding_Backorder>
|
5 |
+
<version>1.0.1</version>
|
6 |
+
</HusseyCoding_Backorder>
|
7 |
+
</modules>
|
8 |
+
<global>
|
9 |
+
<blocks>
|
10 |
+
<backorder>
|
11 |
+
<class>HusseyCoding_Backorder_Block</class>
|
12 |
+
</backorder>
|
13 |
+
</blocks>
|
14 |
+
<helpers>
|
15 |
+
<backorder>
|
16 |
+
<class>HusseyCoding_Backorder_Helper</class>
|
17 |
+
</backorder>
|
18 |
+
</helpers>
|
19 |
+
<models>
|
20 |
+
<backorder>
|
21 |
+
<class>HusseyCoding_Backorder_Model</class>
|
22 |
+
</backorder>
|
23 |
+
<sales>
|
24 |
+
<rewrite>
|
25 |
+
<order_item>HusseyCoding_Backorder_Model_Order_SalesItem</order_item>
|
26 |
+
</rewrite>
|
27 |
+
</sales>
|
28 |
+
</models>
|
29 |
+
<resources>
|
30 |
+
<backorder_setup>
|
31 |
+
<setup>
|
32 |
+
<module>HusseyCoding_Backorder</module>
|
33 |
+
<class>Mage_Catalog_Model_Resource_Setup</class>
|
34 |
+
</setup>
|
35 |
+
</backorder_setup>
|
36 |
+
</resources>
|
37 |
+
</global>
|
38 |
+
<frontend>
|
39 |
+
<layout>
|
40 |
+
<updates>
|
41 |
+
<backorder>
|
42 |
+
<file>backorder.xml</file>
|
43 |
+
</backorder>
|
44 |
+
</updates>
|
45 |
+
</layout>
|
46 |
+
<routers>
|
47 |
+
<backorder>
|
48 |
+
<use>standard</use>
|
49 |
+
<args>
|
50 |
+
<module>HusseyCoding_Backorder</module>
|
51 |
+
<frontName>backorder</frontName>
|
52 |
+
</args>
|
53 |
+
</backorder>
|
54 |
+
</routers>
|
55 |
+
<events>
|
56 |
+
<controller_action_predispatch_checkout>
|
57 |
+
<observers>
|
58 |
+
<frontend_controller_action_predispatch_checkout_backorder>
|
59 |
+
<class>backorder/observer</class>
|
60 |
+
<method>frontendControllerActionPredispatchCheckout</method>
|
61 |
+
</frontend_controller_action_predispatch_checkout_backorder>
|
62 |
+
</observers>
|
63 |
+
</controller_action_predispatch_checkout>
|
64 |
+
<sales_order_place_after>
|
65 |
+
<observers>
|
66 |
+
<frontend_sales_order_place_after_backorder>
|
67 |
+
<class>backorder/observer</class>
|
68 |
+
<method>frontendSalesOrderPlaceAfter</method>
|
69 |
+
</frontend_sales_order_place_after_backorder>
|
70 |
+
</observers>
|
71 |
+
</sales_order_place_after>
|
72 |
+
</events>
|
73 |
+
</frontend>
|
74 |
+
</config>
|
app/code/community/HusseyCoding/Backorder/etc/system.xml
ADDED
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<sections>
|
4 |
+
<backorder translate="label" module="backorder">
|
5 |
+
<label>Backorder</label>
|
6 |
+
<tab>husseycoding</tab>
|
7 |
+
<frontend_type>text</frontend_type>
|
8 |
+
<sort_order>1</sort_order>
|
9 |
+
<show_in_default>1</show_in_default>
|
10 |
+
<show_in_website>1</show_in_website>
|
11 |
+
<show_in_store>1</show_in_store>
|
12 |
+
<groups>
|
13 |
+
<general translate="label">
|
14 |
+
<label>General</label>
|
15 |
+
<frontend_type>text</frontend_type>
|
16 |
+
<sort_order>1</sort_order>
|
17 |
+
<show_in_default>1</show_in_default>
|
18 |
+
<show_in_website>1</show_in_website>
|
19 |
+
<show_in_store>1</show_in_store>
|
20 |
+
<fields>
|
21 |
+
<enabled>
|
22 |
+
<label>Enable Backorder</label>
|
23 |
+
<frontend_type>select</frontend_type>
|
24 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
25 |
+
<sort_order>1</sort_order>
|
26 |
+
<show_in_default>1</show_in_default>
|
27 |
+
<show_in_website>1</show_in_website>
|
28 |
+
<show_in_store>1</show_in_store>
|
29 |
+
</enabled>
|
30 |
+
<ignorestock>
|
31 |
+
<label>Ignore Stock</label>
|
32 |
+
<frontend_type>select</frontend_type>
|
33 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
34 |
+
<sort_order>2</sort_order>
|
35 |
+
<show_in_default>1</show_in_default>
|
36 |
+
<show_in_website>1</show_in_website>
|
37 |
+
<show_in_store>1</show_in_store>
|
38 |
+
<comment>Enable functionality even if product is in stock</comment>
|
39 |
+
</ignorestock>
|
40 |
+
<agreement>
|
41 |
+
<label>Require Agreement</label>
|
42 |
+
<frontend_type>select</frontend_type>
|
43 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
44 |
+
<sort_order>3</sort_order>
|
45 |
+
<show_in_default>1</show_in_default>
|
46 |
+
<show_in_website>1</show_in_website>
|
47 |
+
<show_in_store>1</show_in_store>
|
48 |
+
<comment>Customer must agree to estimated dispatch date for products on the cart page before they can checkout</comment>
|
49 |
+
</agreement>
|
50 |
+
<notmanaged>
|
51 |
+
<label>Enable For Non Stock Managed</label>
|
52 |
+
<frontend_type>select</frontend_type>
|
53 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
54 |
+
<sort_order>4</sort_order>
|
55 |
+
<show_in_default>1</show_in_default>
|
56 |
+
<show_in_website>1</show_in_website>
|
57 |
+
<show_in_store>1</show_in_store>
|
58 |
+
<comment>Enable functionality on products without stock management</comment>
|
59 |
+
</notmanaged>
|
60 |
+
<orderbefore>
|
61 |
+
<label>Show Dispatch Today/Tomorrow</label>
|
62 |
+
<frontend_type>select</frontend_type>
|
63 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
64 |
+
<sort_order>5</sort_order>
|
65 |
+
<show_in_default>1</show_in_default>
|
66 |
+
<show_in_website>1</show_in_website>
|
67 |
+
<show_in_store>1</show_in_store>
|
68 |
+
<comment>Show 'dispatched today if ordered within' notice for products with no lead time</comment>
|
69 |
+
</orderbefore>
|
70 |
+
<cutoff>
|
71 |
+
<label>Order Cut Off Time</label>
|
72 |
+
<frontend_type>text</frontend_type>
|
73 |
+
<sort_order>6</sort_order>
|
74 |
+
<show_in_default>1</show_in_default>
|
75 |
+
<show_in_website>1</show_in_website>
|
76 |
+
<show_in_store>1</show_in_store>
|
77 |
+
<comment>Time after which an order will no longer be dispatched the same day, i.e 5pm</comment>
|
78 |
+
</cutoff>
|
79 |
+
<fixed_holidays>
|
80 |
+
<label>Fixed Holidays</label>
|
81 |
+
<frontend_type>text</frontend_type>
|
82 |
+
<sort_order>7</sort_order>
|
83 |
+
<show_in_default>1</show_in_default>
|
84 |
+
<show_in_website>1</show_in_website>
|
85 |
+
<show_in_store>1</show_in_store>
|
86 |
+
<comment>Comma separated holiday dates in day-month format i.e. 25-12,26-12</comment>
|
87 |
+
</fixed_holidays>
|
88 |
+
<dynamic_holidays>
|
89 |
+
<label>Dynamic Holidays</label>
|
90 |
+
<frontend_type>text</frontend_type>
|
91 |
+
<sort_order>8</sort_order>
|
92 |
+
<show_in_default>1</show_in_default>
|
93 |
+
<show_in_website>1</show_in_website>
|
94 |
+
<show_in_store>1</show_in_store>
|
95 |
+
<comment>Comma separated dynamic holiday dates in format day of week (1-7, Mon-Sun)-week in the month-month i.e. 1-1-5 for May Day (first Monday in May). Use 'last' for last week of the month i.e. 1-last-5</comment>
|
96 |
+
</dynamic_holidays>
|
97 |
+
</fields>
|
98 |
+
</general>
|
99 |
+
</groups>
|
100 |
+
</backorder>
|
101 |
+
</sections>
|
102 |
+
</config>
|
app/code/community/HusseyCoding/Backorder/sql/backorder_setup/install-1.0.0.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
$installer = $this;
|
3 |
+
$installer->addAttribute(Mage_Catalog_Model_Product::ENTITY, 'backorder', array(
|
4 |
+
'type' => 'varchar',
|
5 |
+
'label' => 'Backorder Lead Time',
|
6 |
+
'input' => 'text',
|
7 |
+
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
|
8 |
+
'visible' => true,
|
9 |
+
'required' => false,
|
10 |
+
'user_defined' => true,
|
11 |
+
'searchable' => false,
|
12 |
+
'filterable' => false,
|
13 |
+
'comparable' => false,
|
14 |
+
'visible_on_front' => false,
|
15 |
+
'unique' => false,
|
16 |
+
'apply_to' => 'simple,configurable,bundle,grouped',
|
17 |
+
'is_configurable' => false
|
18 |
+
));
|
app/code/community/HusseyCoding/Backorder/sql/backorder_setup/upgrade-1.0.0-1.0.1.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
$installer = $this;
|
3 |
+
foreach ($installer->getAllAttributeSetIds('catalog_product') as $setid):
|
4 |
+
$attributeid = $installer->getAttributeId('catalog_product', 'backorder');
|
5 |
+
$groupid = $installer->getDefaultAttributeGroupId('catalog_product', $setid);
|
6 |
+
$installer->addAttributeToSet('catalog_product', $setid, $groupid, $attributeid);
|
7 |
+
endforeach;
|
app/code/community/HusseyCoding/Common/etc/system.xml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<tabs>
|
4 |
+
<husseycoding translate="label">
|
5 |
+
<label>Hussey Coding</label>
|
6 |
+
<sort_order>500</sort_order>
|
7 |
+
</husseycoding>
|
8 |
+
</tabs>
|
9 |
+
</config>
|
app/design/frontend/base/default/layout/backorder.xml
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<layout version="0.1.0">
|
3 |
+
<catalog_product_view>
|
4 |
+
<update handle="backorder_layout" />
|
5 |
+
</catalog_product_view>
|
6 |
+
<checkout_cart_index>
|
7 |
+
<update handle="backorder_layout" />
|
8 |
+
</checkout_cart_index>
|
9 |
+
<backorder_layout>
|
10 |
+
<reference name="head">
|
11 |
+
<action method="addItem">
|
12 |
+
<type>skin_js</type>
|
13 |
+
<name>js/backorder.js</name>
|
14 |
+
</action>
|
15 |
+
<action method="addItem">
|
16 |
+
<type>skin_css</type>
|
17 |
+
<name>css/backorder.css</name>
|
18 |
+
</action>
|
19 |
+
</reference>
|
20 |
+
<block type="backorder/estimate" name="backorder" template="backorder/estimate.phtml" parent="before_body_end" />
|
21 |
+
</backorder_layout>
|
22 |
+
</layout>
|
app/design/frontend/base/default/template/backorder/estimate.phtml
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ($this->isEnabled()): ?>
|
2 |
+
<script type="text/javascript">
|
3 |
+
//<![CDATA[
|
4 |
+
var thisbackorder = new backorder();
|
5 |
+
<?php $isproduct = $this->isProduct(); ?>
|
6 |
+
<?php $iscart = $this->isCart(); ?>
|
7 |
+
thisbackorder.isproduct = <?php echo $isproduct; ?>;
|
8 |
+
thisbackorder.iscart = <?php echo $iscart; ?>;
|
9 |
+
thisbackorder.estimatetext = "<?php echo $this->__('Estimated dispatch'); ?>";
|
10 |
+
thisbackorder.orderbefore = <?php echo $this->getOrderBefore(); ?>;
|
11 |
+
thisbackorder.orderbeforetodaytext = "<?php echo $this->__('Dispatched today if ordered within the next'); ?>";
|
12 |
+
thisbackorder.orderbeforetomorrowtext = "<?php echo $this->__('Dispatched tomorrow if ordered within the next'); ?>";
|
13 |
+
thisbackorder.cutoff = "<?php echo $this->getCutOff(); ?>";
|
14 |
+
thisbackorder.now = "<?php echo Mage::getModel('core/date')->timestamp(); ?>";
|
15 |
+
<?php if ($isproduct == 'true'): ?>
|
16 |
+
<?php if ($estimate = $this->getProductEstimate()): ?>
|
17 |
+
thisbackorder.producttype = "<?php echo $this->getProductType(); ?>";
|
18 |
+
<?php if (!is_array($estimate)): ?>
|
19 |
+
thisbackorder.productestimate = "<?php echo $estimate; ?>";
|
20 |
+
<?php else: ?>
|
21 |
+
thisbackorder.productestimate = <?php echo Mage::helper('core')->jsonEncode($estimate); ?>;
|
22 |
+
<?php endif; ?>
|
23 |
+
<?php endif; ?>
|
24 |
+
<?php elseif ($iscart == 'true'): ?>
|
25 |
+
thisbackorder.cartestimates = <?php echo $this->getCartEstimates(); ?>;
|
26 |
+
thisbackorder.itemids = <?php echo $this->getItemIds(); ?>;
|
27 |
+
thisbackorder.delayedtext = "<?php echo $this->__('I understand this product will be delayed'); ?>";
|
28 |
+
thisbackorder.acceptedurl = "<?php echo $this->getUrl('backorder'); ?>";
|
29 |
+
thisbackorder.hasaccepted = <?php echo $this->getHasAccepted(); ?>;
|
30 |
+
thisbackorder.acceptedids = <?php echo $this->getAcceptedIds(); ?>;
|
31 |
+
thisbackorder.acceptenabled = <?php echo $this->acceptEnabled(); ?>;
|
32 |
+
<?php endif; ?>
|
33 |
+
|
34 |
+
if (typeof(spConfig) == "object") {
|
35 |
+
spConfig.getIdOfSelectedProduct = function() {
|
36 |
+
var existingProducts = new Object();
|
37 |
+
for (var i = this.settings.length - 1; i >= 0; i--) {
|
38 |
+
var selected = this.settings[i].options[this.settings[i].selectedIndex];
|
39 |
+
if (selected.config) {
|
40 |
+
for (var iproducts = 0; iproducts < selected.config.products.length; iproducts++) {
|
41 |
+
var usedAsKey = selected.config.products[iproducts] + "";
|
42 |
+
if (existingProducts[usedAsKey] == undefined) {
|
43 |
+
existingProducts[usedAsKey] = 1;
|
44 |
+
} else {
|
45 |
+
existingProducts[usedAsKey] = existingProducts[usedAsKey] + 1;
|
46 |
+
}
|
47 |
+
}
|
48 |
+
}
|
49 |
+
}
|
50 |
+
for (var keyValue in existingProducts) {
|
51 |
+
for (var keyValueInner in existingProducts) {
|
52 |
+
if (Number(existingProducts[keyValueInner]) < Number(existingProducts[keyValue])) {
|
53 |
+
delete existingProducts[keyValueInner];
|
54 |
+
}
|
55 |
+
}
|
56 |
+
}
|
57 |
+
var sizeOfExistingProducts = 0;
|
58 |
+
var currentSimpleProductId = "";
|
59 |
+
for (var keyValue in existingProducts) {
|
60 |
+
currentSimpleProductId = keyValue;
|
61 |
+
sizeOfExistingProducts = sizeOfExistingProducts + 1
|
62 |
+
}
|
63 |
+
|
64 |
+
if (sizeOfExistingProducts == 1) {
|
65 |
+
return currentSimpleProductId;
|
66 |
+
}
|
67 |
+
|
68 |
+
return false;
|
69 |
+
}
|
70 |
+
}
|
71 |
+
|
72 |
+
thisbackorder.afterInit();
|
73 |
+
//]]>
|
74 |
+
</script>
|
75 |
+
<?php endif; ?>
|
app/etc/modules/HusseyCoding_Backorder.xml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<HusseyCoding_Backorder>
|
5 |
+
<active>true</active>
|
6 |
+
<codePool>community</codePool>
|
7 |
+
</HusseyCoding_Backorder>
|
8 |
+
</modules>
|
9 |
+
</config>
|
app/etc/modules/HusseyCoding_Common.xml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<HusseyCoding_Common>
|
5 |
+
<active>true</active>
|
6 |
+
<codePool>community</codePool>
|
7 |
+
</HusseyCoding_Common>
|
8 |
+
</modules>
|
9 |
+
</config>
|
package.xml
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<package>
|
3 |
+
<name>HusseyCoding_Backorder</name>
|
4 |
+
<version>1.0.1</version>
|
5 |
+
<stability>stable</stability>
|
6 |
+
<license uri="http://opensource.org/licenses/osl-3.0.php">OSL</license>
|
7 |
+
<channel>community</channel>
|
8 |
+
<extends/>
|
9 |
+
<summary>Adds dispatch estimate notifications to product pages and the cart.</summary>
|
10 |
+
<description>Adds a dispatch lead time attribute to each product which should be entered as a human readable text string describing the lead time for the product, i.e. 1 week and 3 days. For parent products (grouped, configurable and bundle) the lead time should be entered for the child simple products rather than the parent product - any lead time on a parent product will be ignored.</description>
|
11 |
+
<notes>Initial release.</notes>
|
12 |
+
<authors><author><name>Hussey Coding</name><user>husseycoding</user><email>info@husseycoding.co.uk</email></author></authors>
|
13 |
+
<date>2015-02-25</date>
|
14 |
+
<time>10:30:19</time>
|
15 |
+
<contents><target name="magecommunity"><dir name="HusseyCoding"><dir name="Backorder"><dir name="Block"><file name="Estimate.php" hash="2dadd6ef7986940fb8799229f380adfb"/></dir><dir name="controllers"><file name="IndexController.php" hash="398362af6bd568d1cb5cb616c73d461a"/></dir><dir name="etc"><file name="adminhtml.xml" hash="81e616c4c65ddbd6e92728f8dc8e3fe5"/><file name="config.xml" hash="1411ae42b9029ab35aeda968cac93696"/><file name="system.xml" hash="c3a6eb4358c2718fa834b43aa4f3e9ab"/></dir><dir name="Helper"><file name="Data.php" hash="ad1ba6ca3adc348ed7a3b589ff0c3cb6"/></dir><dir name="Model"><file name="Observer.php" hash="971fa0f7da6d23849fdf856aa21f1499"/><dir name="Order"><file name="SalesItem.php" hash="04de33199c3fac846eefaa9276114183"/></dir></dir><dir name="sql"><dir name="backorder_setup"><file name="install-1.0.0.php" hash="54c2cb1a423fad263b465df516da1ccb"/><file name="upgrade-1.0.0-1.0.1.php" hash="87b1f3a15a9e062691e33be10e39d330"/></dir></dir></dir><dir name="Common"><dir name="etc"><file name="system.xml" hash="6c9ba9f227b9adfc9abf97f17b46fdbf"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="HusseyCoding_Backorder.xml" hash="97f4e05e024b0baa9f51ed3be9929168"/><file name="HusseyCoding_Common.xml" hash="31e82d3d9b3179c2fa9e002f9669da47"/></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="backorder.xml" hash="04d971a9830ffb2240b348783fec82bc"/></dir><dir name="template"><dir name="backorder"><file name="estimate.phtml" hash="19cec7e672b96251439191e7292768cc"/></dir></dir></dir></dir></dir></target><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><dir name="js"><file name="backorder.js" hash="56cedcd8276b8081566a418bb860cb38"/></dir><dir name="css"><file name="backorder.css" hash="f9601103bb20f597f9b58ec31d53ca6a"/></dir></dir></dir></dir></target></contents>
|
16 |
+
<compatible/>
|
17 |
+
<dependencies><required><php><min>5.1.0</min><max>6.0.0</max></php></required></dependencies>
|
18 |
+
</package>
|
skin/frontend/base/default/css/backorder.css
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
.dispatch-estimate span { color:#eb340a; }
|
2 |
+
.dispatch-nolead span { font-weight:bold; }
|
3 |
+
.backorder-accept { margin-bottom:10px; }
|
skin/frontend/base/default/js/backorder.js
ADDED
@@ -0,0 +1,211 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
var backorder = Class.create({
|
2 |
+
afterInit: function() {
|
3 |
+
this.orderbeforestring = false;
|
4 |
+
if (this.isproduct) {
|
5 |
+
if (this.productestimate || this.orderbefore) {
|
6 |
+
if (this.producttype == "grouped") {
|
7 |
+
this.initGrouped();
|
8 |
+
} else if (this.producttype == "configurable") {
|
9 |
+
this.initConfigurable();
|
10 |
+
} else if (this.producttype == "bundle") {
|
11 |
+
this.initBundle();
|
12 |
+
} else {
|
13 |
+
if (this.productestimate) {
|
14 |
+
$$(".availability")[0].insert({after: "<p class=\"dispatch-estimate\">" + this.estimatetext + ": <span>" + this.productestimate + "</span></p>"});
|
15 |
+
} else {
|
16 |
+
$$(".availability")[0].insert({after: "<div class=\"dispatch-nolead\">" + this.getOrderBeforeString() + "</div>"});
|
17 |
+
}
|
18 |
+
}
|
19 |
+
}
|
20 |
+
} else if (this.iscart) {
|
21 |
+
$$("#shopping-cart-table .product-name").each(function(e) {
|
22 |
+
var estimate = this.cartestimates.shift();
|
23 |
+
var itemid = this.itemids.shift();
|
24 |
+
var checked = "";
|
25 |
+
if (this.hasaccepted || this.acceptedids.indexOf(itemid) >= 0) {
|
26 |
+
checked = "checked ";
|
27 |
+
}
|
28 |
+
if (!estimate && this.orderbefore) {
|
29 |
+
e.insert({after: "<div class=\"dispatch-nolead\">" + this.getOrderBeforeString() + "</div>"});
|
30 |
+
} else if (estimate) {
|
31 |
+
e.insert({after: "<div class=\"dispatch-estimate\">" + this.estimatetext + ": <span>" + estimate + "</span></div>"});
|
32 |
+
if (this.acceptenabled) {
|
33 |
+
e.next().insert({after: "<div class=\"backorder-accept\"><input " + checked + "type=\"checkbox\" class=\"checkbox\" name=\"backorder[" + itemid + "]\" /><span>" + this.delayedtext + "</span></div>"});
|
34 |
+
}
|
35 |
+
}
|
36 |
+
}.bind(this));
|
37 |
+
this.addCheckboxListeners();
|
38 |
+
}
|
39 |
+
},
|
40 |
+
getOrderBeforeString: function() {
|
41 |
+
if (!this.orderbeforestring) {
|
42 |
+
var cutoff = new Date(this.cutoff * 1000);
|
43 |
+
var now = new Date(this.now * 1000);
|
44 |
+
var difference = this.cutoff - this.now;
|
45 |
+
var minutes = difference / 60;
|
46 |
+
var hours = Math.floor(minutes / 60);
|
47 |
+
minutes -= hours * 60;
|
48 |
+
minutes = Math.floor(minutes);
|
49 |
+
if (!hours) {
|
50 |
+
var estimate = minutes + " minutes";
|
51 |
+
} else {
|
52 |
+
var estimate = hours + " hours and " + minutes + " minutes";
|
53 |
+
}
|
54 |
+
if (cutoff.getDay() > now.getDay()) {
|
55 |
+
this.orderbeforestring = this.orderbeforetomorrowtext + " <span>" + estimate + "</span>";
|
56 |
+
} else {
|
57 |
+
this.orderbeforestring = this.orderbeforetodaytext + " <span>" + estimate + "</span>";
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
return this.orderbeforestring;
|
62 |
+
},
|
63 |
+
initGrouped: function() {
|
64 |
+
$$(".grouped-items-table input").each(function(e) {
|
65 |
+
var productid = e.name.match(/[0-9]+/);
|
66 |
+
if (this.productestimate[productid]) {
|
67 |
+
e.up("tr").down().insert({bottom: "<p class=\"dispatch-estimate\">" + this.estimatetext + ": <span>" + this.productestimate[productid] + "</span></p>"});
|
68 |
+
} else if (this.orderbefore) {
|
69 |
+
e.up("tr").down().insert({bottom: "<p class=\"dispatch-nolead\">" + this.getOrderBeforeString() + "</p>"});
|
70 |
+
}
|
71 |
+
}.bind(this));
|
72 |
+
},
|
73 |
+
initConfigurable: function() {
|
74 |
+
this.addConfigurableSelectListeners();
|
75 |
+
this.updateConfigurableEstimate();
|
76 |
+
},
|
77 |
+
addConfigurableSelectListeners: function() {
|
78 |
+
$$(".product-options select").each(function(e) {
|
79 |
+
e.observe("change", function(el) {
|
80 |
+
this.updateConfigurableEstimate();
|
81 |
+
}.bind(this));
|
82 |
+
}.bind(this));
|
83 |
+
},
|
84 |
+
updateConfigurableEstimate: function() {
|
85 |
+
this.removeEstimate();
|
86 |
+
var productid = spConfig.getIdOfSelectedProduct();
|
87 |
+
if (productid) {
|
88 |
+
if (this.productestimate[productid]) {
|
89 |
+
$$(".availability")[0].insert({after: "<p class=\"dispatch-estimate\">" + this.estimatetext + ": <span>" + this.productestimate[productid] + "</span></p>"});
|
90 |
+
} else if (this.orderbefore) {
|
91 |
+
$$(".availability")[0].insert({after: "<p class=\"dispatch-nolead\">" + this.getOrderBeforeString() + "</p>"});
|
92 |
+
}
|
93 |
+
}
|
94 |
+
},
|
95 |
+
initBundle: function() {
|
96 |
+
this.addBundleOptionListeners();
|
97 |
+
this.updateBundleEstimate();
|
98 |
+
},
|
99 |
+
addBundleOptionListeners: function() {
|
100 |
+
this.addBundleSelectListeners();
|
101 |
+
this.addBundleInputListeners();
|
102 |
+
},
|
103 |
+
addBundleSelectListeners: function() {
|
104 |
+
$$(".product-options select").each(function(e) {
|
105 |
+
e.observe("change", function(el) {
|
106 |
+
this.updateBundleEstimate();
|
107 |
+
}.bind(this));
|
108 |
+
}.bind(this));
|
109 |
+
},
|
110 |
+
addBundleInputListeners: function() {
|
111 |
+
$$(".product-options input").each(function(e) {
|
112 |
+
e.observe("change", function(el) {
|
113 |
+
this.updateBundleEstimate();
|
114 |
+
}.bind(this));
|
115 |
+
}.bind(this));
|
116 |
+
},
|
117 |
+
updateBundleEstimate: function() {
|
118 |
+
this.removeEstimate();
|
119 |
+
var estimates = [];
|
120 |
+
var selected = $("product_addtocart_form").serialize(true);
|
121 |
+
$H(selected).each(function(e) {
|
122 |
+
if (e.key.indexOf("bundle_option") == 0 && e.value != "") {
|
123 |
+
var bundleid = e.key.match(/[0-9]+/);
|
124 |
+
var value = e.value.toString();
|
125 |
+
if (value.indexOf(",")) {
|
126 |
+
var values = value.split(",");
|
127 |
+
} else {
|
128 |
+
var values = [value];
|
129 |
+
}
|
130 |
+
values.each(function(value) {
|
131 |
+
var estimate = this.getBundleEstimate(bundleid, value);
|
132 |
+
if (estimate) {
|
133 |
+
estimates.push(estimate);
|
134 |
+
}
|
135 |
+
}.bind(this));
|
136 |
+
}
|
137 |
+
}.bind(this));
|
138 |
+
var estimate = this.getLongestBundleEstimate(estimates);
|
139 |
+
if (estimate) {
|
140 |
+
$$(".availability")[0].insert({after: "<p class=\"dispatch-estimate\">" + this.estimatetext + ": <span>" + estimate + "</span></p>"});
|
141 |
+
} else if (this.orderbefore) {
|
142 |
+
$$(".availability")[0].insert({after: "<p class=\"dispatch-nolead\">" + this.getOrderBeforeString() + "</p>"});
|
143 |
+
}
|
144 |
+
},
|
145 |
+
getBundleEstimate: function(bundleid, value) {
|
146 |
+
if (this.productestimate[bundleid]) {
|
147 |
+
if (this.productestimate[bundleid][value]) {
|
148 |
+
var epoch = this.productestimate[bundleid][value]["epoch"];
|
149 |
+
var estimate = this.productestimate[bundleid][value]["estimate"];
|
150 |
+
|
151 |
+
return [epoch, estimate];
|
152 |
+
}
|
153 |
+
}
|
154 |
+
|
155 |
+
return false;
|
156 |
+
},
|
157 |
+
getLongestBundleEstimate: function(estimates) {
|
158 |
+
var epoch = 0;
|
159 |
+
var estimate = "";
|
160 |
+
estimates.each(function(e) {
|
161 |
+
if (e[0] > epoch) {
|
162 |
+
epoch = e[0];
|
163 |
+
estimate = e[1];
|
164 |
+
}
|
165 |
+
}.bind(this));
|
166 |
+
|
167 |
+
if (estimate) {
|
168 |
+
return estimate;
|
169 |
+
}
|
170 |
+
|
171 |
+
return false;
|
172 |
+
},
|
173 |
+
removeEstimate: function() {
|
174 |
+
if ($$(".dispatch-estimate")[0]) {
|
175 |
+
$$(".dispatch-estimate")[0].remove();
|
176 |
+
} else if ($$(".dispatch-nolead")[0]) {
|
177 |
+
$$(".dispatch-nolead")[0].remove();
|
178 |
+
}
|
179 |
+
},
|
180 |
+
addCheckboxListeners: function() {
|
181 |
+
if (this.acceptenabled) {
|
182 |
+
$$(".backorder-accept").each(function(e) {
|
183 |
+
e.down("input").observe("click", function(el) {
|
184 |
+
this.updateAccepted();
|
185 |
+
}.bind(this));
|
186 |
+
e.down("span").observe("click", function(el) {
|
187 |
+
if (el.target.previous().checked) {
|
188 |
+
el.target.previous().checked = false;
|
189 |
+
} else {
|
190 |
+
el.target.previous().checked = true;
|
191 |
+
}
|
192 |
+
this.updateAccepted();
|
193 |
+
}.bind(this));
|
194 |
+
}.bind(this));
|
195 |
+
}
|
196 |
+
},
|
197 |
+
updateAccepted: function() {
|
198 |
+
var accepted = true;
|
199 |
+
var itemids = [];
|
200 |
+
$$(".backorder-accept input").each(function(e) {
|
201 |
+
if (e.checked) {
|
202 |
+
itemids.push(e.name.match(/[0-9]+/));
|
203 |
+
} else {
|
204 |
+
accepted = false;
|
205 |
+
}
|
206 |
+
}.bind(this));
|
207 |
+
new Ajax.Request(this.acceptedurl, {
|
208 |
+
parameters: {accepted: accepted, itemids: itemids.join()}
|
209 |
+
});
|
210 |
+
}
|
211 |
+
});
|