HusseyCoding_Backorder - Version 1.0.1

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 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
+ });