Follow us on Twitter X-Cart on Facebook Wiki
Shopping cart software Solutions for online shops and malls

"Fake" orders (or how do a cart become an order ?)
 
Reply
   X-Cart forums > X-Cart 5 > Modifying the design and features (X-Cart 5)
 
Thread Tools Search this Thread
  #1  
Old 09-26-2019, 12:51 AM
 
Ed B. Ed B. is online now
 

eXpert
  
Join Date: Apr 2016
Posts: 221
 

Default "Fake" orders (or how do a cart become an order ?)

I would like to create a "fake checkout page" so that a "fake order" can be placed. To be more precise, the fake orders will have all "properties" that the real orders have, but they don't trigger the actions that real orders do, except being saved in the database, and they shouldn't show up in the order list.

It looks like all I would need is to save the order with the property is_order set to 0.
However, I have no idea on how to achieve this.

What I have figured out so far is that when one places an order, doActionCheckout()
function in the controller class is called. Which in turn calls the function registerOrderPackaging( , ) from Core/OrderHistory.php. This function, in turn, calls for
registerPlaceOrder, registerEvent which somehow register the order event in the
xc_order_history_events table. But I don't see exactly how the order is saved in xc_orders table. So my first question is: is there any way to save a "fake order" placed on "fake" ckeckout page in the table with is_order=0?


Otherwise, I have so far succeeded to decorate the /Model/Order.php class so that it
has a new column "is_fake", and "fake orders" have is_fake set to 1. Unfortunately I can't set is_order=0 this way because getCart() has no such property as is_order.
So another way to achieve my goal would be to decorate all classes involving the treatment of orders (like email notification, admin order list, customer order list etc.) ignore the orders with the property is_fake = 1. But to start with, how do I find complete set of such classes?


Thank you very much in advance.
__________________
X-cart 5.2.12, php 5.6
Ed from Grenoble, France
Reply With Quote
  #2  
Old 09-26-2019, 05:17 AM
  cflsystems's Avatar 
cflsystems cflsystems is offline
 

Veteran
  
Join Date: Apr 2007
Posts: 13,600
 

Default Re: "Fake" orders (or how do a cart become an order ?)

This is where an IDE can help a lot...


Search for "is_order" shows this in classes/XLite/Model/Repo/Cart.php




Code:
/** * Define query for markAsOrder() method * * @paraminteger $orderId Order id * * @return \Doctrine\DBAL\Statement|void */ protectedfunctiondefineMarkAsOrderQuery($orderId) { $stmt = $this->_em->getConnection()->prepare( 'UPDATE'.$this->_class->getTableName() .' ' .'SET is_order = :flag ' .'WHERE order_id = :id' ); if ($stmt) { $stmt->bindValue(':flag', 1); $stmt->bindValue(':id', $orderId); } else { $stmt = null; } return$stmt; }




And in classes/XLite/Model/Repo/Order.php


Code:
/** * Define query for markAsCart() method * * @paraminteger $orderId Order id * * @return \Doctrine\DBAL\Statement|void */ protectedfunctiondefineMarkAsCartQuery($orderId) { $stmt = $this->_em->getConnection()->prepare( 'UPDATE'.$this->_class->getTableName() .' ' .'SET is_order = :flag ' .'WHERE order_id = :id' ); if ($stmt) { $stmt->bindValue(':flag', 0); $stmt->bindValue(':id', $orderId); } else { $stmt = null; } return$stmt; }
__________________
Steve Stoyanov
CFLSystems.com
Web Development
Reply With Quote

The following user thanks cflsystems for this useful post:
Ed B. (10-01-2019)
  #3  
Old 09-28-2019, 12:04 AM
 
Ed B. Ed B. is online now
 

eXpert
  
Join Date: Apr 2016
Posts: 221
 

Default Re: "Fake" orders (or how do a cart become an order ?)

Thank you very much. O.K, I got that
There is a function markAsOrder in the Model/Repo/Cart.php
which is used in Model/Cart.php
Code:
/** * Mark cart as order * * @return void */ public function markAsOrder() { parent::markAsOrder(); if ($this instanceof \XLite\Model\Cart) { $this->assignOrderNumber(); } $this->getRepository()->markAsOrder($this->getOrderId()); }
which in turn is called in Model/Order.php

Code:
public function processSucceed() { $this->markAsOrder(); ....


So I presume I only would have to modify somewhere in the chain the value of is_order, I am done? And probably the simplest thing is to decorate Model/Order.php to have something like
Code:
public function processSucceed() { if (!isFake()) { $this->markAsOrder(); } ....
And maybe to be on the safe side, I can add couple of lines to set is_order=0 when I have a fake order?
__________________
X-cart 5.2.12, php 5.6
Ed from Grenoble, France
Reply With Quote
  #4  
Old 09-29-2019, 09:03 AM
 
Ed B. Ed B. is online now
 

eXpert
  
Join Date: Apr 2016
Posts: 221
 

Default Re: "Fake" orders (or how do a cart become an order ?)

Actually things doesn't go that easy. Any attempt to override the function processSuceed() in \XLite\Model\Order from \Vendor\Module\Model\Order ends up with an internal server error. I can't even do
Code:
public function processSucceed() { parent::processSuceed(); }


Any ideas?
__________________
X-cart 5.2.12, php 5.6
Ed from Grenoble, France
Reply With Quote
  #5  
Old 09-29-2019, 09:50 AM
  cflsystems's Avatar 
cflsystems cflsystems is offline
 

Veteran
  
Join Date: Apr 2007
Posts: 13,600
 

Default Re: "Fake" orders (or how do a cart become an order ?)

You are not doing something right with the file then. Internal server error will indicate an error with the file itself or php syntax not with the execution of the function.


Example - If it works for QT it should work for you too - classes/XLite/Module/CDev/Coupons/Model/Order.php


Code:
/** * Called when an order successfully placed by a client * * @return void */ public function processSucceed() { parent::processSucceed(); foreach ($this->getUsedCoupons() as $usedCoupons) { $usedCoupons->markAsUsed(); } }
__________________
Steve Stoyanov
CFLSystems.com
Web Development
Reply With Quote

The following user thanks cflsystems for this useful post:
Ed B. (10-01-2019)
  #6  
Old 10-01-2019, 11:34 PM
 
Ed B. Ed B. is online now
 

eXpert
  
Join Date: Apr 2016
Posts: 221
 

Default Re: "Fake" orders (or how do a cart become an order ?)

Thank you very much, I really should "reread" my codes (well, I did, lots of times). It was a matter of misplaced braces.


So, somehow I can't do things like
Code:
public function markAsOrder() { if (isfake) {parent::markAsCart();} else parent::markAsOrder(); }
, this leading to an error (no such property, function name must start...)


Thus I had to reproduce the entire processSucceed function with the if clause
at the beginning. In any case, it works like a charm. Now my question is, why does this work in the first place? For example, how come we don't see these fake orders in order list page?


The order list page in the admin area uses the widget XLite/View/ItemsList/Model/Order/Admin/Search.php. This class, contains nothing about the property is_order. I also noticed that when is_order=0, there is no orderNumber, but then again, this property is used everywhere to sort orders, but there is no search condition that requires orderNumber not to be null. I saw that in the class Model/Repo/Order.php
"alternativeIdentifier" is defined to be orderNumber, so I deorated in Module/Vendor/Repo/Order.php
Code:
<?php namespace XLite\Module\Vendor\Module\Model\Repo abstract class Order extends \XLite\Model\Repo\Order implements \XLite\Base\IDecorator { protected $alternativeIdentifier = array( array('orderId'), ); }
but no fake orders are shown in the list. So, what is going on?


If I wanted to fake orders in the order list among the real ones, what would I have to do? It is not that I need, but this mystery really bothers me.
__________________
X-cart 5.2.12, php 5.6
Ed from Grenoble, France
Reply With Quote
  #7  
Old 10-02-2019, 05:35 AM
  cflsystems's Avatar 
cflsystems cflsystems is offline
 

Veteran
  
Join Date: Apr 2007
Posts: 13,600
 

Default Re: "Fake" orders (or how do a cart become an order ?)

That's tricky and related to Doctrine. While I am not 100% (almost 100% sure though) sure this is how XC determines which records are orders and which are not - is_order = 1 for placed orders


The Repo Order class when creating the query builder uses "placedOnly" parameter. Search the class fot it and you will see how it adds condition to select only records that are an instance of Order.


The Model Order class has these Doctrine annotations
@DiscriminatorColumn
@DiscriminatorMap


These 2 tell DQL what determines the "instance of" condition



https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/annotations-reference.html#discriminatorcolumn
__________________
Steve Stoyanov
CFLSystems.com
Web Development
Reply With Quote
  #8  
Old 10-02-2019, 10:56 PM
 
Ed B. Ed B. is online now
 

eXpert
  
Join Date: Apr 2016
Posts: 221
 

Default Re: "Fake" orders (or how do a cart become an order ?)

Quote:
Originally Posted by cflsystems
That's tricky and related to Doctrine. While I am not 100% (almost 100% sure though) sure this is how XC determines which records are orders and which are not - is_order = 1 for placed orders


The Repo Order class when creating the query builder uses "placedOnly" parameter. Search the class fot it and you will see how it adds condition to select only records that are an instance of Order.
Well,
Code:
/** * Create a new QueryBuilder instance that is prepopulated for this entity name * * @param string $alias Table alias OPTIONAL * @param string $indexBy The index for the from. OPTIONAL * @param boolean $placedOnly Use only orders or orders + carts OPTIONAL * * @return \XLite\Model\QueryBuilder\AQueryBuilder */ public function createQueryBuilder($alias = null, $indexBy = null, $placedOnly = true) { $result = parent::createQueryBuilder($alias, $indexBy); if ($placedOnly) { $result->andWhere($result->getMainAlias() . ' NOT INSTANCE OF XLite\Mod el\Cart'); } return $result; }

I didn't find the string "INSTANCE OF"... in any other class.



Are you implying that somehow because of
Code:
* @DiscriminatorColumn (name="is_order", type="integer", length=1) * @DiscriminatorMap ({1 = "XLite\Model\Order", 0 = "XLite\Model\Cart"})
my "fake orders" become instance of XLite\Model\Cart so that get ignored
in the search? Thus if I wanted search including fake orders, I would somehow
need to use

Code:
createQueryBuilder(o,'','false);

or something like that?


Quote:


The Model Order class has these Doctrine annotations
@DiscriminatorColumn
@DiscriminatorMap


These 2 tell DQL what determines the "instance of" condition



https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/annotations-reference.html#discriminatorcolumn
__________________
X-cart 5.2.12, php 5.6
Ed from Grenoble, France
Reply With Quote
  #9  
Old 10-03-2019, 04:27 AM
  cflsystems's Avatar 
cflsystems cflsystems is offline
 

Veteran
  
Join Date: Apr 2007
Posts: 13,600
 

Default Re: "Fake" orders (or how do a cart become an order ?)

Yes. The DescriminatorColumn defines the column in the table and the DescriminatorMap maps its value to class.


So if you need only non-orders create new query with placeOnly equal false.


Alternatively you can just decorate the Order model class and add another field for your own use - if true it is your fake order. Then use it in a query to find your own records.
__________________
Steve Stoyanov
CFLSystems.com
Web Development
Reply With Quote
  #10  
Old 10-04-2019, 05:38 AM
 
Ed B. Ed B. is online now
 

eXpert
  
Join Date: Apr 2016
Posts: 221
 

Default Re: "Fake" orders (or how do a cart become an order ?)

Quote:
Originally Posted by cflsystems
Yes. The DescriminatorColumn defines the column in the table and the DescriminatorMap maps its value to class.


So if you need only non-orders create new query with placeOnly equal false.


Alternatively you can just decorate the Order model class and add another field for your own use - if true it is your fake order. Then use it in a query to find your own records.


I think I got it. Well, if I create new query with placeOnly equal false, I will get both real and fake orders, right? Since I am removing the "where" clause.


Now my next problem is this: in the end, I would like to have ItemsList of real orders only (as there are currently) and ItemsList of fake orders only. In the future I might want to have a "mixed" list, but let's forget it for now. How can I do this?


Can I override from itemslist class the default parameter of createquerybuilder set in repo class? At a first glance, this doesn't look possible. If there is such a way, it will really save me...



Of course, I can decorate the repository class, but this would affect all itemslists concerning products. Since these itemslists don't seem to call createquerybuilder with the third argument (they don't seem to directly call createquerybuilder, so the third argument could be only set by default in the repository class), this means I will have to decorate all itemslist classes where I only want "real" orders.


I also have an extra property in the order model, but using this instead of is_order=0 gives me the same problem (well, at least I won't have to decorate the createquerybuilder function), i.e., I will have to redecorate all existing product lists not to show the fake orders.



I am tempted to create a new model "fake orders" which are in one to one to the orders that are fake, and this should solve all my problems, but I wonder if there could be a simpler way.
__________________
X-cart 5.2.12, php 5.6
Ed from Grenoble, France
Reply With Quote
Reply
   X-Cart forums > X-Cart 5 > Modifying the design and features (X-Cart 5)


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT -8. The time now is 08:45 AM.

   

 
X-Cart forums © 2001-2018