multi store, manual activation account with prestashop - prestashop

I use multi-store option with prestashop. I would like to pass customers in the second store to manual activation after registration.
Actually I set $customer->active = 0; in authentication.php.
all registration customer in both websites are inactive after registration.
Is there a way to set $customer->active = 0; just for one website.
I think to get shop_id but I don't know how to develop my idea.

In Prestashop 1.6 :
You can get the id_shop with the Context object.
So, I think you can do something like this :
If you know the id_shop (suppose the id_shop = 1)
if (Context::getContext()->shop->id == 1) {
$customer->active = 0;
} else {
$customer->active = 1;
}
Hope it helps.
EDIT
Updated answer to get the id_shop from context because the Customer object doesn't handle it until it's added.
RE-EDIT
In the Customer class (/classes/Customer.php) customize the add() function.
Add this line around the line 212 (after the "last_passwd_gen" declaration) :
$this->active = ($this->id_shop == 3) ? false : true;
But the best solution for you is to create an override of the function.

Related

Automatically increase stock after order - Prestashop

I manually manage my stocks on Prestashop. I am looking for a solution to automatically return the initial stock after a sales order.
For example, a product is ordered in two copies with an initial stock of 7. I would like the stock to remain at 7 after the order and not at 5.
Do you know a technique that would allow me to realize this automatically?
Put a Hook on Order Confirmation (displayOrderConfirmation) in a new module (you can generate one at https://validator.prestashop.com/) and check whats inside the cart then put it again in your stocks :
public function hookDisplayOrderConfirmation($params) {
$order = $params['order'];
$cart = new Cart($order->id_cart);
$products = $cart->getProducts();
foreach ($products as $product) {
$removed_qty = (int) $product['quantity'];
$past_qty = (int) StockAvailable::getQuantityAvailableByProduct($product['id_product'], $product['id_product_attribute']);
$new_qty = $removed_qty + $past_qty;
StockAvailable::setQuantity($product['id_product'], $product['id_product_attribute'], $new_qty);
}
}

Sales Order Confirmation Report - SalesConfirmDP

I am modifying the SalesConfirmDP class and trying to add the CustVendExternalItem.ExternalItemTxt field into a new field I have created.
I have tried a couple of things but I do not think my syntax was correct i.e I declare the CustVendExternalItem table in the class declaration. But then when I try to insert CustVendExternalItem.ExternalItemTxt into my new field, it does not populate, I guess there must be a method which I need to include?
If anyone has any suggestion it would be highly appreciated.
Thank you in advance.
private void setSalesConfirmDetailsTmp(NoYes _confirmTransOrTaxTrans)
{
DocuRefSearch docuRefSearch;
// Body
salesConfirmTmp.JournalRecId = custConfirmJour.RecId;
if(_confirmTransOrTaxTrans == NoYes::Yes)
{
if (printLineHeader)
{
salesConfirmTmp.LineHeader = custConfirmTrans.LineHeader;
}
else
{
salesConfirmTmp.LineHeader = '';
}
salesConfirmTmp.ItemId = this.itemId();
salesConfirmTmp.Name = custConfirmTrans.Name;
salesConfirmTmp.Qty = custConfirmTrans.Qty;
salesConfirmTmp.SalesUnitTxt = custConfirmTrans.salesUnitTxt();
salesConfirmTmp.SalesPrice = custConfirmTrans.SalesPrice;
salesConfirmTmp.DlvDate = custConfirmTrans.DlvDate;
salesConfirmTmp.DiscPercent = custConfirmTrans.DiscPercent;
salesConfirmTmp.DiscAmount = custConfirmTrans.DiscAmount;
salesConfirmTmp.LineAmount = custConfirmTrans.LineAmount;
salesConfirmTmp.CurrencyCode = custConfirmJour.CurrencyCode;
salesConfirmTmp.PrintCode = custConfirmTrans.TaxWriteCode;
if (pdsCWEnabled)
{
salesConfirmTmp.PdsCWUnitId = custConfirmTrans.pdsCWUnitId();
salesConfirmTmp.PdsCWQty = custConfirmTrans.PdsCWQty;
}
**salesConfirmTmp.ExternalItemText = CustVendExternalItem.ExternalItemTxt;**
if ((custFormletterDocument.DocuOnConfirm == DocuOnFormular::Line)
|| (custFormletterDocument.DocuOnConfirm == DocuOnFormular::All))
{
docuRefSearch = DocuRefSearch::newTypeIdAndRestriction(custConfirmTrans,
custFormletterDocument.DocuTypeConfirm,
DocuRestriction::External);
salesConfirmTmp.Notes = Docu::concatDocuRefNotes(docuRefSearch);
}
salesConfirmTmp.InventDimPrint = this.printDimHistory();
Well, AX cannot guess which record you need, there is a helper class CustVendExternalItemDescription to deal with it:
boolean found;
str externalItemId;
...
[found, externalItemId, salesConfirmTmp.ExternalItemText] = CustVendExternalItemDescription::findExternalItemDescription(
ModuleCustVend::Cust,
custConfirmTrans.ItemId,
custConfirmTrans.inventDim(),
custConfirmJour.OrderAccount,
CustTable::find(custConfirmJour.OrderAccount).CustItemGroupId);
The findExternalItemDescription method returns more information than you need here, but you have to define variables to store it anyway.
Well, the steps to solve this problem are fairly easy and i will try to give you a step by step approach how to solve this problem.
1) Are you initialising CustVendExternalItem properly? Make a record of the same and initialise it as Jan has shown above, then debug your code and see if the value is being initialised in your DP class.
2)If your value is being initialised correctly, but it is not showing up in the report design there can be multiple issues such as:
Overlapping of text boxes.
Insufficient space for the given field
Some report parameter/property not being set correctly which causes
your value not to show up on the report.
Check these one by one and you should end up arriving towards a solution

Why can I not use Continuation when using a proxy class to access MS CRM 2013?

So I have a standard service reference proxy calss for MS CRM 2013 (i.e. right-click add reference etc...) I then found the limitation that CRM data calls limit to 50 results and I wanted to get the full list of results. I found two methods, one looks more correct, but doesn't seem to work. I was wondering why it didn't and/or if there was something I'm doing incorrectly.
Basic setup and process
crmService = new CrmServiceReference.MyContext(new Uri(crmWebServicesUrl));
crmService.Credentials = System.Net.CredentialCache.DefaultCredentials;
var accountAnnotations = crmService.AccountSet.Where(a => a.AccountNumber = accountNumber).Select(a => a.Account_Annotation).FirstOrDefault();
Using Continuation (something I want to work, but looks like it doesn't)
while (accountAnnotations.Continuation != null)
{
accountAnnotations.Load(crmService.Execute<Annotation>(accountAnnotations.Continuation.NextLinkUri));
}
using that method .Continuation is always null and accountAnnotations.Count is always 50 (but there are more than 50 records)
After struggling with .Continutation for a while I've come up with the following alternative method (but it seems "not good")
var accountAnnotationData = accountAnnotations.ToList();
var accountAnnotationFinal = accountAnnotations.ToList();
var index = 1;
while (accountAnnotationData.Count == 50)
{
accountAnnotationData = (from a in crmService.AnnotationSet
where a.ObjectId.Id == accountAnnotationData.First().ObjectId.Id
select a).Skip(50 * index).ToList();
accountAnnotationFinal = accountAnnotationFinal.Union(accountAnnotationData).ToList();
index++;
}
So the second method seems to work, but for any number of reasons it doesn't seem like the best. Is there a reason .Continuation is always null? Is there some setup step I'm missing or some nice way to do this?
The way to get the records from CRM is to use paging here is an example with a query expression but you can also use fetchXML if you want
// Query using the paging cookie.
// Define the paging attributes.
// The number of records per page to retrieve.
int fetchCount = 3;
// Initialize the page number.
int pageNumber = 1;
// Initialize the number of records.
int recordCount = 0;
// Define the condition expression for retrieving records.
ConditionExpression pagecondition = new ConditionExpression();
pagecondition.AttributeName = "address1_stateorprovince";
pagecondition.Operator = ConditionOperator.Equal;
pagecondition.Values.Add("WA");
// Define the order expression to retrieve the records.
OrderExpression order = new OrderExpression();
order.AttributeName = "name";
order.OrderType = OrderType.Ascending;
// Create the query expression and add condition.
QueryExpression pagequery = new QueryExpression();
pagequery.EntityName = "account";
pagequery.Criteria.AddCondition(pagecondition);
pagequery.Orders.Add(order);
pagequery.ColumnSet.AddColumns("name", "address1_stateorprovince", "emailaddress1", "accountid");
// Assign the pageinfo properties to the query expression.
pagequery.PageInfo = new PagingInfo();
pagequery.PageInfo.Count = fetchCount;
pagequery.PageInfo.PageNumber = pageNumber;
// The current paging cookie. When retrieving the first page,
// pagingCookie should be null.
pagequery.PageInfo.PagingCookie = null;
Console.WriteLine("#\tAccount Name\t\t\tEmail Address");while (true)
{
// Retrieve the page.
EntityCollection results = _serviceProxy.RetrieveMultiple(pagequery);
if (results.Entities != null)
{
// Retrieve all records from the result set.
foreach (Account acct in results.Entities)
{
Console.WriteLine("{0}.\t{1}\t\t{2}",
++recordCount,
acct.EMailAddress1,
acct.Name);
}
}
// Check for more records, if it returns true.
if (results.MoreRecords)
{
// Increment the page number to retrieve the next page.
pagequery.PageInfo.PageNumber++;
// Set the paging cookie to the paging cookie returned from current results.
pagequery.PageInfo.PagingCookie = results.PagingCookie;
}
else
{
// If no more records are in the result nodes, exit the loop.
break;
}
}

Redbean: How does one get last inserted id of owned Bean?

I use RedBeanPHP 3.5.1 for ORM in my MVP project (powered by Nette FW).
I need to get ID of the last inserted element, that is owned by element from another table. Below you can find method representing functionality which I just described:
public function createSite($userId, $siteName, $feedUrl, $reloadTime, $reloadRate){
$site = R::dispense('site');
$site->user_id = $userId;
$site->name = $siteName;
$site->feed = $feedUrl;
$site->reload_time = $reloadTime;
$site->reload_rate = $reloadRate;
$user = R::load('user', $userId);
$user->ownSite[] = $site;
$id = R::store($user);
return $id;
}
Now I would assume that line
$id = R::store($user);
would store site ID into $id variable since it is owned by already existing user. Instead of that it fills variable with user ID that I have no further use for.
So my question is: How do I get last inserted ID of owned bean that was just created by calling R::store() method on parent (just loaded) bean? Is there an implementation on this in RedBean or do I have to do this manually?
I browsed every corner of RedBeanPHP project web but so far no luck.
Thanks for possible suggestions, guys.
Using common sense I finally figured out how to solve this elegantly and since no one answered my question so far let my just do that myself.
Since R::store($user) is capable of storing both $user and $site, there is misleadingly no need to store $site object manually.
But if you need to get last inserted id of owned bean, there is really no harm in doing so. By storing $site object framework will do the exact same thing and on top of that it returns resired id.
So the correct method implementation looks like this:
public function createSite($userId, $siteName, $feedUrl, $reloadTime, $reloadRate){
$site = R::dispense('site');
$site->user_id = $userId;
$site->name = $siteName;
$site->feed = $feedUrl;
$site->reload_time = $reloadTime;
$site->reload_rate = $reloadRate;
$user = R::load('user', $userId);
$user->ownSite[] = $site;
$id = R::store($site);
R::store($user);
return $id;
}
So in conclusion, hats off to RedBeanPHP ORM FW and I sincerely hope this helps people with similar problem in the future.
There is a function called R::findLast('...')
$last_record = R::findLast('...');
Not sure if this would have been a correct answer 7 years ago but at least now there is no need to do any kind of extra work:
$shop = R::dispense( 'shop' );
$shop->name = 'Antiques';
$vase = R::dispense( 'product' );
$vase->price = 25;
$shop->ownProductList[] = $vase
R::store( $shop );
echo $vase->$id; // <-- yes, id which was created by database is present here

SQL to Magento model understanding

Understanding Magento Models by reference of SQL:
select * from user_devices where user_id = 1
select * from user_devices where device_id = 3
How could I perform the same using my magento models? getModel("module/userdevice")
Also, how can I find the number of rows for each query
Following questions have been answered in this thread.
How to perform a where clause ?
How to retrieve the size of the result set ?
How to retrieve the first item in the result set ?
How to paginate the result set ? (limit)
How to name the model ?
You are referring to Collections
Some references for you:
http://www.magentocommerce.com/knowledge-base/entry/magento-for-dev-part-5-magento-models-and-orm-basics
http://alanstorm.com/magento_collections
http://www.magentocommerce.com/wiki/1_-_installation_and_configuration/using_collections_in_magento
lib/varien/data/collection/db.php and lib/varien/data/collection.php
So, assuming your module is set up correctly, you would use a collection to retrieve multiple objects of your model type.
Syntax for this is:
$yourCollection = Mage::getModel('module/userdevice')->getCollection()
Magento has provided some great features for developers to use with collections. So your example above is very simple to achieve:
$yourCollection = Mage::getModel('module/userdevice')->getCollection()
->addFieldToFilter('user_id', 1)
->addFieldToFilter('device_id', 3);
You can get the number of objects returned:
$yourCollection->count() or simply count($yourCollection)
EDIT
To answer the question posed in the comment: "what If I do not require a collection but rather just a particular object"
This depends if you still require both conditions in the original question to be satisfied or if you know the id of the object you wish to load.
If you know the id of the object then simply:
Mage::getModel('module/userdevice')->load($objectId);
but if you wish to still load based on the two attributes:
user_id = 1
device_id = 3
then you would still use a collection but simply return the first object (assuming that only one object could only ever satisfy both conditions).
For reuse, wrap this logic in a method and place in your model:
public function loadByUserDevice($userId, $deviceId)
{
$collection = $this->getResourceCollection()
->addFieldToFilter('user_id', $userId)
->addFieldToFilter('device_id', $deviceId)
->setCurPage(1)
->setPageSize(1)
;
foreach ($collection as $obj) {
return $obj;
}
return false;
}
You would call this as follows:
$userId = 1;
$deviceId = 3;
Mage::getModel('module/userdevice')->loadByUserDevice($userId, $deviceId);
NOTE:
You could shorten the loadByUserDevice to the following, though you would not get the benefit of the false return value should no object be found:
public function loadByUserDevice($userId, $deviceId)
{
$collection = $this->getResourceCollection()
->addFieldToFilter('user_id', $userId)
->addFieldToFilter('device_id', $deviceId)
;
return $collection->getFirstItem();
}