Actually task:
I purchasers do a discount with 2 order of 5 % from 6 order - 7% with 10 and all the next 10%. Here it is necessary that all this automatically considered in the personal account of the buyer. the discount should be considered of the purchase price, excluding shipping charges. And the discount should be considered only when the previous order status changes such as the order is paid. buyers in the office can see how much they already have orders and what they discount it should, and Yes, I forgot, the category of sale discounts should not apply.
In General, the goal is simple and fast approach is solved for 2-3 hours. But we will not look for easy ways, and to fully integrate the functionality such discounts in VirtueMart. As a result of the store will offer a new section where you can create and change the discount.
The discount will be calculated on the basis of the number of orders user in the list of orders with the status - are transported and delivered. This revision does not change rates for certain goods, and adds a discount on the purchase price when ordering. This is a complete modification of VirtueMart, includes all the changes to the code store.
Similarly, the tasks related to discount the amount of the order, from the referral link from different cities, etc.
Actually solution:
1. For a start, go into phpMyAdmin and create table jos_vm_castom1 in the database. Here we will store the information about our discounts. At the same time add the field castom1_discount in table jos_vm_orders. This table stores information about completed transactions, and we will record it our discount, current at the time of purchase. Don't forget about the prefixes.
CREATE TABLE IF NOT EXISTS `jos_vm_castom1` (
`castom1_id` int(11) NOT NULL auto_increment,
`castom1_val` int(11) default NULL ,
`publish` int(1) default NULL ,
`castom1_from` int(11) default NULL ,
`castom1_category` varchar(128) NOT NULL default '',
PRIMARY KEY (`castom1_id`)
)
ALTER TABLE `jos_vm_orders` ADD `castom1_discount` varchar(50) NOT NULL default ''
2. Add language values in the file /administrator/components/com_virtuemart/languages/common/russian.php. The-same will be done for all installed in the shop languages:
'PHPSHOP_CASTOM1_FORM_MNU' => 'Discounts for regular customers',
'PHPSHOP_CASTOM1_TIP' => 'Enter a comma-separated id categories, which discount will not be charged. The discount will not be charged and in subcategories.',
'PHPSHOP_CASTOM1_QUANTITY' => 'The number of necessary transactions',
'PHPSHOP_CASTOM1_CATEGORIES' => 'The excluded categories',
'PHPSHOP_CASTOM1_YOO' => 'Your discount is',
'PHPSHOP_CASTOM1_YOO2' => 'Discount permanent user',
'PHPSHOP_CASTOM1_TITLE' => 'Our shop offers discounts to regular customers. You've done',
'PHPSHOP_CASTOM1_N' => 'shopping',
3. Now add in the admin panel store a reference to the management of our discounts. It is marked with yellow marker on the screenshots. To do this, open the file /administrator/components/com_virtuemart/header.php and paste the menu code block:
<li class="item-smenu vmicon vmicon-16-content">
<a href="<?php $sess->purl($_SERVER['PHP_SELF']."?pshop_mode=admin&page=admin.castom1_list") ?>"><?php echo $VM_LANG->_('PHPSHOP_CASTOM1_FORM_MNU') ?></a>
<hr />
</li>
You should do this about, below 303 line, however great a value of no. Now we have a link in the menu, but you push it so far. First you create files that will shape the page, as in the screenshots. Such files will be three:
4. Create a file
/administrator/components/com_virtuemart/classes/ps_castom1.php
/administrator/components/com_virtuemart/html/admin.castom1_form.php
/administrator/components/com_virtuemart/html/admin.castom1_list.php
Because we do not need special filters and buttons, code of these files is simple and standard. You can download all three files in the archive, or write them yourself. Bring them the code I am not going to.
Download archive with files ps_castom1.php admin.castom1_form.php admin.castom1_list.php
5. Now we have a semi-working Amin-part of the functionality. It remains only to add a button to delete discounts. For this, in the
/administrator/components/com_virtuemart/toolbar.virtuemart.php
insert, after approximately 53 lines
"admin.castom1_list" => "castom1Delete",
6. The last thing you want to admin panel earned is to assign a new function castom1Delete, Castom1Update, Castom1Add.
To do this, open the menu virtuemart item List of modules. In front of the item admin open a List of options. Click "New"
function name: castom1Delete
Class name: ps_castom1
Method of the class: delete
The right to a function: admin, storeadmin
Similarly, prescribes two Castom1Update and Castom1Add.
7. You can now engage our discounts in the basket, letters and reports.
In the beginning, add the two functions in the class ps_product. Later we will easily be able to call them where we need to. This is the function that determines whether a given product in a запрешенной category or not. And its auxiliary function that defines all child categories, which are banned. Open the file /administrator/components/com_virtuemart/classes/ps_product.php and at the bottom of the class, add before the closing class bracket of two functions:
// Скидка постоянным пользователям. Проверка запрещенных категорий.
function get_castom1_rate($product_id,$castom1_categories) {
if(!$castom1_categories)return TRUE;
$castom1_categories=$this->get_castom1_categories_child($castom1_categories);
$db = new ps_DB;
$count = "SELECT COUNT(*) as num_rows FROM #__k2_items WHERE id=(SELECT itemID FROM #__k2mart WHERE productID=" . (int)$product_id.") AND catid IN($castom1_categories)";
$db->query($count);
$db->next_record();
if( $db->f('num_rows')) return FALSE;
return TRUE;
}
// Get all the child categories of prohibited
function get_castom1_categories_child($castom1_categories) {
$db = new ps_DB;
$ret = $castom1_categories;
while($castom1_categories){
$catid = array();
$q = "SELECT id FROM #__k2_categories WHERE parent IN($castom1_categories)";
$db->query($q);
while($db->next_record()){
$catid[]=$db->f('id');
}
$castom1_categories=implode(',',$catid);
if($castom1_categories)$ret .=','.$castom1_categories;
}
return $ret;
}
Because in my case the shop was built on a bunch of K2 + VirtueMart, I had to get a category of K2. In the case of VirtueMart still easier.
If you use VirtueMart category, then these functions will be
// Discount constant users. Checking the blocked categories.
function get_castom1_rate($product_id,$castom1_categories) {
if(!$castom1_categories) return TRUE;
require_once (CLASSPATH."ps_product_category.php");
$ps_product_category = new ps_product_category;
$castom1_categories=explode(',',$this->get_castom1_categories_child($castom1_categories));
if(in_array($ps_product_category->get_cid( $product_id ), $castom1_categories)) return FALSE;
return TRUE;
}
// Get all the child categories of prohibited
function get_castom1_categories_child($castom1_categories) {
$db = new ps_DB;
$ret = $castom1_categories;
while($castom1_categories){
$catid = array();
$query = "SELECT a.category_id "
. "FROM #__{vm}_category AS a "
. "LEFT JOIN #__{vm}_category_xref AS b "
. "ON a.category_id = b.category_child_id "
. "WHERE b.category_parent_id IN($castom1_categories) "
. "AND a.category_publish = 'Y' ";
$db->query($query);
while($db->next_record()){
$catid[]=$db->f('category_id');
}
$castom1_categories=implode(',',$catid);
if($castom1_categories)$ret .=','.$castom1_categories;
}
return $ret;
}
8. Let's move to the basket. Here we need to do a series of changes to both files.
/administrator/components/com_virtuemart/html/basket.php
/administrator/components/com_virtuemart/html/ro_basket.php
In both files similar changes. Look for approximately 52 line
$product_rows = Array();
and add the following
// Discount for regular users.
$castom1_discount = 0;
$castom1_discount_val = 0;
$castom1_categories = '';
$ps_vendor_id = $_SESSION["ps_vendor_id"];
$auth = $_SESSION['auth'];
$db = new ps_DB;
$countfields = 'count(*) as num_rows';
$count = "SELECT $countfields FROM #__{vm}_orders o ";
$q = "WHERE o.vendor_id='$ps_vendor_id' ";
$q .= "AND (order_status='S' OR order_status='R') ";
$q .= "AND user_id='" . $auth["user_id"] . "' ";
$count .= $q;
$db->query($count);
$db->next_record();
$num_rows = $db->f('num_rows');
if($num_rows){
$q = "SELECT * FROM #__{vm}_castom1 WHERE publish=1 ORDER BY castom1_val LIMIT 100";
$db->setQuery($q); $db->query();
while ($db->next_record()) {
if($num_rows>=($db->f("castom1_from"))){
$castom1_discount_val =$db->f("castom1_val");
$castom1_categories =$db->f("castom1_category");
}
}
}
Then look for a section of code in the area 132 line
if( $auth["show_price_including_tax"] == 1 ) {
$product_price = $price["product_price"] * ($my_taxrate+1);
} else {
$product_price = $price["product_price"];
}
and add the following
// Discount for regular users
if($castom1_discount_val&&$ps_product->get_castom1_rate($cart[$i]["product_id"],$castom1_categories)){
$castom1_discount += $product_price*$castom1_discount_val/100;
}
Next, look for a section of code in the area of 314 line
$order_total += $shipping_total + $total;
$total_undiscounted += $shipping_total;
and add the following in the file basket.php
// Discount constant users.
if($castom1_discount){
$castom1_discount=round( $castom1_discount, 2 );
$order_total -= $castom1_discount;
$_SESSION['castom1_discount']=$castom1_discount;
$castom1_discount=$GLOBALS['CURRENCY_DISPLAY']->getFullValue($castom1_discount);
}
in the file ro_basket.php
// Discount constant users.
$castom1_discount=round( $castom1_discount, 2 );
$order_total -= $castom1_discount;
if($castom1_discount)$castom1_discount=$GLOBALS['CURRENCY_DISPLAY']->getFullValue($castom1_discount);
Now hold our variable in the template basket. Look for the following section of code in both files
$tpl->set_vars( Array(
'product_rows' => $product_rows,
'subtotal_display' => $subtotal_display,
'discount_before' => $discount_before,
'discount_after' => $discount_after,
and add there
'castom1_discount' => $castom1_discount,
9. Now let templates basket - four of them and it is necessary to change everything. Fortunately, no changes a lot.
В файлах
/components/com_virtuemart/themes/template/templates/basket/basket_b2b.html.php
/components/com_virtuemart/themes/template/templates/basket/basket_b2c.html.php
Ищем участок кода
if($discount_after) { ?>
<tr class="sectiontableentry1">
<td colspan="4" align="right"><?php echo $VM_LANG->_('PHPSHOP_COUPON_DISCOUNT') ?>:
</td>
<td colspan="3" align="right"><?php echo $coupon_display ?></td>
</tr>
<?php }
and add below
if($castom1_discount) { ?>
<tr class="sectiontableentry1">
<td colspan="4" align="right"><?php echo $VM_LANG->_('PHPSHOP_CASTOM1_YOO') ?>:
</td>
<td colspan="3" align="right"><?php echo $castom1_discount ?></td>
</tr>
<?php } ?>
Similarly in files
/components/com_virtuemart/themes/template/templates/basket/ro_basket_b2b.html.php
/components/com_virtuemart/themes/template/templates/basket/ro_basket_b2c.html.php
Ищем участок кода
if( $coupon_discount_after ) { ?>
<tr class="sectiontableentry1">
<td colspan="4" align="right"><?php echo $VM_LANG->_('PHPSHOP_COUPON_DISCOUNT') ?>:
</td>
<td align="right"><?php echo $coupon_display ?></td>
</tr>
<?php }
and add below
if($castom1_discount) { ?>
<tr class="sectiontableentry1">
<td colspan="4" align="right"><?php echo $VM_LANG->_('PHPSHOP_CASTOM1_YOO') ?>:
</td>
<td colspan="3" align="right"><?php echo $castom1_discount ?></td>
</tr>
<?php } ?>
Now when placing an order, the buyer sees its proposal. But that's not all, let's sent letters and reports.
10. Open the file /administrator/components/com_virtuemart/classes/ps_checkout.php and begin to edit.
Looking for a plot of code, about 970 line:
// Collect all fields and values to store them!
$fields = array(
'user_id' => $auth["user_id"],
'vendor_id' => $ps_vendor_id,
'order_number' => $order_number,
'user_info_id' => $d["ship_to_info_id"],
'ship_method_id' => @urldecode($d["shipping_rate_id"]),
And type in there
'castom1_discount' => $castom1_discount,
Looking for a plot of code about 1231 line:
// Clear the sensitive Session data
$_SESSION['ccdata']['order_payment_name'] = "";
$_SESSION['ccdata']['order_payment_number'] = "";
$_SESSION['ccdata']['order_payment_expire_month'] = "";
$_SESSION['ccdata']['order_payment_expire_year'] = "";
$_SESSION['ccdata']['credit_card_code'] = "";
$_SESSION['coupon_discount'] = "";
And type in there
$_SESSION['castom1_discount'] = "";
Looking for a plot of code about 1308 line:
/* DISCOUNT HANDLING */
if( !empty($_SESSION['coupon_discount']) ) {
$totals['coupon_discount'] = floatval($_SESSION['coupon_discount']);
}
else {
$totals['coupon_discount'] = 0.00;
}
And add below
/* Discount for regular users */
if( !empty($_SESSION['castom1_discount']) ) {
$totals['castom1_discount'] = floatval($_SESSION['castom1_discount']);
}
else {
$totals['castom1_discount'] = 0;
}
Looking for a plot of code around line 1344:
$d['order_total'] = $totals['order_total'] = $tmp_subtotal
+ $totals['order_tax']
+ $totals['order_shipping']
+ $totals['order_shipping_tax']
- $totals['coupon_discount']
And type in there
- $totals['castom1_discount']
Looking for a plot of code about 1538 string:
if( (!empty( $_SESSION['coupon_discount'] ) || !empty( $d['payment_discount'] ))
&& PAYMENT_DISCOUNT_BEFORE == '1' ) {
And change the
if( (!empty( $_SESSION['coupon_discount'] ) || !empty( $d['payment_discount'] ) || !empty( $_SESSION['castom1_discount'] ))
&& PAYMENT_DISCOUNT_BEFORE == '1' ) {
Slightly below are looking for
$use_coupon_discount= @$_SESSION['coupon_discount'];
And add below
$use_castom1_discount= @$_SESSION['castom1_discount'];
if( !empty( $_SESSION['castom1_discount'] )) {
if( $auth["show_price_including_tax"] == 1 ) {
$use_castom1_discount = $_SESSION['castom1_discount'] / ($tax_rate+1);
}
}
Slightly below are looking for
$factor = (100 * ($use_coupon_discount + @$d['payment_discount'])) / $this->_subtotal;
And change the
$factor = (100 * ($use_castom1_discount + $use_coupon_discount + @$d['payment_discount'])) / $this->_subtotal;
Looking for a plot of code about 1585 string:
if( (!empty( $_SESSION['coupon_discount'] ) || !empty( $d['payment_discount'] ))
&& PAYMENT_DISCOUNT_BEFORE != '1' ) {
And change the
if( (!empty( $_SESSION['coupon_discount'] ) || !empty( $d['payment_discount'] ) || !empty( $_SESSION['castom1_discount'] ))
&& PAYMENT_DISCOUNT_BEFORE == '1' ) {
Slightly below are looking for
if( (!empty( $_SESSION['coupon_discount'] ) || !empty( $d['payment_discount'] ))
&& PAYMENT_DISCOUNT_BEFORE == '1' ) {
$use_coupon_discount= @$_SESSION['coupon_discount'];
And change the
if( (!empty( $_SESSION['coupon_discount'] ) || !empty( $d['payment_discount'] ) || !empty( $_SESSION['castom1_discount'] ))
&& PAYMENT_DISCOUNT_BEFORE == '1' ) {
$use_coupon_discount= @$_SESSION['coupon_discount'];
$use_castom1_discount= @$_SESSION['castom1_discount'];
if( !empty( $_SESSION['castom1_discount'] )) {
if( $auth["show_price_including_tax"] == 1 ) {
$use_castom1_discount = $_SESSION['castom1_discount'] / ($tax_rate+1);
}
}
Slightly below are looking for
$factor = (100 * ($use_coupon_discount + @$d['payment_discount'])) / $this->_subtotal;
And change the
$factor = (100 * ($use_castom1_discount + $use_coupon_discount + @$d['payment_discount'])) / $this->_subtotal;
Below are looking for
if( (!empty( $_SESSION['coupon_discount'] ) || !empty( $d['payment_discount'] ))
&& PAYMENT_DISCOUNT_BEFORE != '1' ) {
// Here we need to re-calculate the Discount
// because we assume the Discount is "including Tax"
$discounted_total = @$d['order_subtotal_withtax'] - @$_SESSION['coupon_discount'] - @$d['payment_discount'];
And change the
if( (!empty( $_SESSION['coupon_discount'] ) || !empty( $d['payment_discount'] ) || !empty( $_SESSION['castom1_discount'] ))
&& PAYMENT_DISCOUNT_BEFORE != '1' ) {
// Here we need to re-calculate the Discount
// because we assume the Discount is "including Tax"
$discounted_total = @$d['order_subtotal_withtax'] - @$_SESSION['coupon_discount'] - @$d['payment_discount'] - @$_SESSION['castom1_discount'] ;
Below the function function email_receipt($order_id) look for approximately string 1884
$order_total = $db->f("order_total");
$order_discount = $db->f("order_discount");
$coupon_discount = $db->f("coupon_discount");
And add below
$castom1_discount = $db->f("castom1_discount");
At the same functions are looking for twice about string 2055 и 2087
if( !empty($coupon_discount)) {
/* following 2 lines added by Erich for coupon hack */
$shopper_message .= $VM_LANG->_('PHPSHOP_COUPON_DISCOUNT',false) . ": ";
$shopper_message .= $CURRENCY_DISPLAY->getFullValue($coupon_discount, '', $db->f('order_currency')) . "\n";
}
And add below
if( !empty($castom1_discount)) {
$shopper_message .= $VM_LANG->_('PHPSHOP_CASTOM1_YOO',false) . ": ";
$shopper_message .= $CURRENCY_DISPLAY->getFullValue($castom1_discount, '', $db->f('order_currency')) . "\n";
}
Below are looking for a section of code
// These are a lot of vars to import for the email confirmation
$template->set_vars(array(
'is_email_to_shopper' => true,
'db' => $db,
'dboi' => $dboi,
'dbbt' => $dbbt,
'dbst' => $dbst,
'ps_product' => $ps_product,
'shippingfields' => $shippingfields,
And stick in there
'castom1_discount' => $castom1_discount,
11. Open the file /components/com_virtuemart/themes/default/templates/order_emails/confirmation_email.tpl.php. In two places find
if ($coupon_discount > 0 || $coupon_discount < 0) {
?>
<tr class="Stil1">
<td align="right" colspan="4"><?php echo $VM_LANG->_('PHPSHOP_COUPON_DISCOUNT') ?>: </td>
<td><?php echo $coupon_discount_plusminus. ' '.$CURRENCY_DISPLAY->getFullValue(abs($coupon_discount),
'', $db->f('order_currency')) ?></td>
</tr>
<?php
}
And in each case, add a bottom
if ($castom1_discount > 0 || $castom1_discount < 0) {
?>
<tr class="Stil1">
<td align="right" colspan="4"><?php echo $VM_LANG->_('PHPSHOP_CASTOM1_YOO') ?>: </td>
<td><?php echo ' -'.$CURRENCY_DISPLAY->getFullValue(abs($castom1_discount), '', $db->f('order_currency')) ?></td>
</tr>
<?php
}
12. Open the file /administrator/components/com_virtuemart/html/order.order_printdetails.php and look for the code
$coupon_discount = $db->f("coupon_discount");
if( $coupon_discount > 0 ) {
$subtotal -= $coupon_discount;
?>
<tr>
<td colspan="4" align="right"><?php echo $VM_LANG->_('PHPSHOP_COUPON_DISCOUNT') ?>:
</td>
<td align="right"><?php
echo "- ".$CURRENCY_DISPLAY->getFullValue( $coupon_discount, '', $db->f('order_currency') ); ?>
</td>
</tr>
<?php
}
under him write bottom
$castom1_discount = $db->f("castom1_discount");
if( $castom1_discount > 0 ) {
$subtotal -= $castom1_discount;
?>
<tr>
<td colspan="4" align="right"><?php echo $VM_LANG->_('PHPSHOP_CASTOM1_YOO2') ?>:
</td>
<td align="right"><?php
echo "- ".$CURRENCY_DISPLAY->getFullValue( $castom1_discount, '', $db->f('order_currency') ); ?>
</td>
</tr>
<?php
}
Below, around line 354
$total = $db->f("order_subtotal") + $tax_total + $db->f("order_shipping") - $db->f("coupon_discount");
change the
$total = $db->f("order_subtotal") + $tax_total + $db->f("order_shipping") - $db->f("coupon_discount") - $db->f("castom1_discount");
13. Open the file /components/com_virtuemart/themes/default/templates/pages/account.order_details.tpl.php. About line 404.
$coupon_discount = $db->f("coupon_discount");
$order_discount = $db->f("order_discount");
bottom add
$castom1_discount = $db->f("castom1_discount");
Below are looking for two times
if( $coupon_discount > 0 ) {
?>
<tr>
<td colspan="4" align="right"><?php echo $VM_LANG->_('PHPSHOP_COUPON_DISCOUNT') ?>:
</td>
<td align="right"><?php
echo "- ".$CURRENCY_DISPLAY->getFullValue( $coupon_discount, '', $db->f('order_currency') ); ?>
</td>
</tr>
<?php
}
bottom add every time
if( $castom1_discount > 0 ) {
?>
<tr>
<td colspan="4" align="right"><?php echo $VM_LANG->_('PHPSHOP_CASTOM1_YOO') ?>:
</td>
<td align="right"><?php
echo "- ".$CURRENCY_DISPLAY->getFullValue( $castom1_discount, '', $db->f('order_currency') ); ?>
</td>
</tr>
<?php
}
14. Open the file /administrator/components/com_virtuemart/html/order.order_print.php About line 419
/* COUPON DISCOUNT */
$coupon_discount = $db->f("coupon_discount");
bottom add
$castom1_discount = $db->f("castom1_discount");
Below are looking for two times
if( $coupon_discount > 0 || $coupon_discount < 0) {
?>
<tr>
<td align="right" colspan="7"><strong><?php echo $VM_LANG->_('PHPSHOP_COUPON_DISCOUNT') ?>:</strong></td>
<td width="5%" align="right" style="padding-right: 5px;"><?php
echo "- ".$GLOBALS['CURRENCY_DISPLAY']->getFullValue( $coupon_discount, '', $db->f('order_currency') ); ?>
</td>
</tr>
<?php
}
bottom add every time
if( $castom1_discount > 0 || $castom1_discount < 0) {
?>
<tr>
<td align="right" colspan="7"><strong><?php echo $VM_LANG->_('PHPSHOP_CASTOM1_YOO2') ?>:</strong></td>
<td width="5%" align="right" style="padding-right: 5px;"><?php
echo "- ".$GLOBALS['CURRENCY_DISPLAY']->getFullValue( $castom1_discount, '', $db->f('order_currency') ); ?>
</td>
</tr>
<?php
}
Actually, all. Then we need to output the size of the discount in the personal account of the buyer. To do this, open the file
/components/com_virtuemart/themes/default/templates/pages/account.index.tpl.php
and add a new line to the table markup
<tr>
<td>
<?php
// Discount for regular users.
echo $VM_LANG->_('PHPSHOP_CASTOM1_TITLE');
$castom1_discount_val = 0;
$ps_vendor_id = $_SESSION["ps_vendor_id"];
$auth = $_SESSION['auth'];
$db = new ps_DB;
$countfields = 'count(*) as num_rows';
$count = "SELECT $countfields FROM #__{vm}_orders o ";
$q = "WHERE o.vendor_id='$ps_vendor_id' ";
$q .= "AND (order_status='S' OR order_status='R') ";
$q .= "AND user_id='" . $auth["user_id"] . "' ";
$count .= $q;
$db->query($count);
$db->next_record();
$num_rows = $db->f('num_rows');
if($num_rows){
$q = "SELECT * FROM #__{vm}_castom1 WHERE publish=1 ORDER BY castom1_val LIMIT 100";
$db->setQuery($q); $db->query();
while ($db->next_record()) {
if($num_rows>=($db->f("castom1_from"))){
$castom1_discount_val =$db->f("castom1_val");
}
}
}
echo ' <strong style="font-size:130%;color:blue">'.$num_rows.'</strong> ';
echo $VM_LANG->_('PHPSHOP_CASTOM1_N');
echo '. '.$VM_LANG->_('PHPSHOP_CASTOM1_YOO');
echo ' <strong style="font-size:130%;color:blue">'.$castom1_discount_val.' %</strong>';
?>
<hr />
</td>
</tr>
If you think it's too long, you may order it to us.