Doctrine 2 date in where-clause (querybuilder) - doctrine-orm

I've the following problem: I want a where-clause that checks if a user is active AND if he has the right date.
A user contains the following:
State
Startdate
Enddate
So, State should stay on 1, then he should look for state = 1 AND the current date is between the start and enddate. I've the following right now, and it works fine. But the start and enddate is not required. So it could be NULL. How can i get a query like:
SELECT *
FROM user/entity/user
WHERE
state = 1
AND (
(startdate <= CURRENT_DATE AND enddate >= CURRENT_DATE)
OR startdate == NULL
OR enddate == NULL
)
, so i get all my active users, and not only the temporary users.
I've set up the following code right now:
Repository:
public function searchUser($columns, $order_by, $order)
{
//Create a Querybuilder
$qb = $this->_em->createQueryBuilder();
//andx is used to build a WHERE clause like (expression 1 AND expression 2)
$or = $qb->expr()->andx();
//Select all from the User-Entity
$qb->select('u')
->from('User\Entity\User', 'u');
foreach($columns as $column => $name)
{
if($column == 'state')
{
if($columns['state']['value'] == '1') {
$or = $this->betweenDate($qb, $or);
$or = $this->like($columns, $qb, $or);
} elseif($columns['state']['value'] == '2') {
$or = $this->like($columns, $qb, $or);
} elseif($columns['state']['value'] == '3') {
$or = $this->outOfDate($qb, $or);
}
} else {
//Get a where clause from the like function
$or = $this->like($columns, $qb, $or);
}
}
//Set the where-clause
$qb->where($or);
//When there is a order_by, set it with the given parameters
if(isset($order_by)) {
$qb->orderBy("u.$order_by", $order);
}
//Make the query
$query = $qb->getQuery();
/*echo('<pre>');
print_r($query->getResult());
echo('</pre>');*/
//Return the result
return $query->getResult();
}
public function betweenDate($qb, $or)
{
$or->add($qb->expr()->lte("u.startdate", ":currentDate"));
$or->add($qb->expr()->gte("u.enddate", ":currentDate"));
//$or->add($qb->expr()->orx($qb->expr()->eq("u.startdate", null)));
$qb->setParameter('currentDate', new \DateTime('midnight'));
return $or;
}
//This one works perfect
public function like($columns, $qb, $or)
{
//Foreach column, get the value from the inputfield/dropdown and check if the value
//is in the given label.
foreach($columns as $label=>$column){
$value = $column['value'];
$or->add($qb->expr()->like("u.$label", ":$label"));
$qb->setParameter($label, '%' . $value . '%');
}
return $or;
}
I use this "usersearch" also for other fields. So it should pick all the data out of the database, only state is different because "out of date" is not in the database. So it has to check differently. Hope somebody can help.
Problem solved
$startdate = $qb->expr()->gt("u.startdate", ":currentDate");
$enddate = $qb->expr()->lt("u.enddate", ":currentDate");
$or->add($qb->expr()->orX($startdate, $enddate));

That's how I would build the where clause:
//CONDITION 1 -> STATE = 1
$state = $qb->expr()->eq( 'state', ':state' );
//CONDITION 2 -> startdate <= CURRENT_DATE AND enddate >= CURRENT_DATE
$betweenDates = $qb->expr()->andX(
$qb->expr()->lte("u.startdate", ":currentDate"),
$qb->expr()->gte("u.enddate", ":currentDate")
);
//CONDITION 3 -> startdate == NULL
$startDateNull = $qb->expr()->isNull( 'startdate' );
//CONDITION 4 -> enddate == NULL
$endDateNull = $qb->expr()->isNull( 'enddate' );
//CONDITION 5 -> <CONDITION 2> OR <CONDITION 3> OR <CONDITION 4>
$dates = $qb->expr()->orX( $betweenDates, $startDateNull, $endDateNull );
//CONDITION 6 -> <CONDITION 1> AND <CONDITION 5>
$whereClause = $qb->expr()->andX( $state, $dates );

Related

How to edit list elements in kotlin or add to second list?

I tried to edit a list in-place but wasn't able to get it working. Now trying to edit individual elements and add them to a second list. However the second list remains null and does not get updated. Any help would be appreciated.
var localFiles: MutableList<String> = File(localPath).list().toMutableList()
var localFileDates: MutableList<String>? = null
val iterateLocal = localFileDates?.listIterator()
for (item in localFiles) {
var date = item.takeLast(10).take(6)
if (date.matches("[0-9]+".toRegex()) and (date.length == 6) and (date != null) and (date != "null")) {
iterateLocal?.add(item.takeLast(10).take(6))
}
}
println(networkFiles) // prints correct outpu
println(localFileDates) // prints null
You need init localFileDates variable:
var localFileDates = MutableList()
var localFiles: MutableList<String> = File(localPath).list().toMutableList()
var localFileDates = MutableList<String>()
val iterateLocal = localFileDates?.listIterator()
for (item in localFiles) {
var date = item.takeLast(10).take(6)
if (date.matches("[0-9]+".toRegex()) and (date.length == 6) and (date != null) and (date != "null")) {
iterateLocal?.add(item.takeLast(10).take(6))
}
}
println(networkFiles) // prints correct outpu
println(localFileDates) // prints correct
It is better to use map{..} function to create a copy of the list with updated values.
val localFiles = File(localPath).list()?.toMutableList() ?: listOf()
val localFileDates = localFiles.mapNotNull { item ->
val date = item.takeLast(10).take(6)
if (date.matches("[0-9]{6}".toRegex()) {
date
} else {
null
}
}
println(localFiles)
println(localFileDates)
I use the mapNotNull{..} function calls the block for every element of the list and builds the new list only from non-null values.
You do not need var in your code, explicit type names can be omitted too.
The condition can be simplified - no need for the null check, the regular expression filters our the data == "null" case, the length check can be included into the regex too. The date variable can be re-used too.
A more idiomatic (and readable) way:
val localFileDates = File(localPath).list().map { it.takeLast(10).take(6) }.filter {
it.matches("[0-9]+".toRegex()) && (it.length == 6) && (it != "null")
}
Also I suggest you create a named function for takeLast(10).take(6) and the condition to make it clear what is the intent of these lines of code.

Doctrine - How to hydrate a collection when using query builder

A previous question I asked was to do with hydrating a result set when using Doctrine and query builder. My issue was how to return an array and their sub-sets:
This was for a single result set and the answer was quite simple:
$qb = $this->stoneRepository->createQueryBuilder('S');
$query = $qb->addSelect('A','P','I','C')
->leftJoin('S.attribute', 'A')
->leftJoin('A.category', 'C')
->innerJoin('S.product' , 'P')
->innerJoin('S.image' , 'I')
->where('S.id = :sid')
->setParameter('sid', (int) $stone_id)
->getQuery();
$resultArray = $query->getOneOrNullResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);
return $resultArray;
My next question is how to do this exact same thing for a collection? This is what I have tried:
public function fetchAll()
{
$qb = $this->stoneRepository->createQueryBuilder('S');
$qb->addSelect('A','P','I','C')
->leftJoin('S.attribute', 'A')
->leftJoin('A.category', 'C')
->innerJoin('S.product' , 'P')
->innerJoin('S.image' , 'I')
->where('S.state=:state')
->setParameter('state' , 1 );
$adapter = new DoctrineAdapter( new ORMPaginator( $qb ) );
$collection = new StoneCollection($adapter);
return $collection;
}
The problem I am facing with this solution is that the join tables are not being populated and I am ending up with a collection of empty results.
The StoneCollection class simply extends paginator:
<?php
namespace Api\V1\Rest\Stone;
use Zend\Paginator\Paginator;
class StoneCollection extends Paginator
{
}
I am thinking that perhaps the best mehod is to get an array and to page the array?
EDIT::
I have this working although I am not keen on it as I hit the DB twice. The first time to build the array (Which is the entire result set which could be very big for some applications) and then the second time to page the results which is then returned to HAL in ApiGility for processing...
Ideally this should be done in one go however I am not sure how to hydrate the results in a single instance...
public function fetchAll( $page = 1 )
{
$qb = $this->stoneRepository->createQueryBuilder('S');
$qb->addSelect('A','P','I','C')
->leftJoin('S.attribute', 'A')
->leftJoin('A.category', 'C')
->innerJoin('S.product' , 'P')
->innerJoin('S.image' , 'I')
->where('S.state=:state')
->setParameter('state' , 1 );
$resultArray = $qb->getQuery()->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);
$paginator = new \Zend\Paginator\Paginator(new \Zend\Paginator\Adapter\ArrayAdapter($resultArray));
$paginator->setCurrentPageNumber($page);
return $paginator;
}
The Answer to this is as I have above:
I have this working although I am not keen on it as I hit the DB twice. The first time to build the array (Which is the entire result set which could be very big for some applications) and then the second time to page the results which is then returned to HAL in ApiGility for processing...
Ideally this should be done in one go however I am not sure how to hydrate the results in a single instance...
public function fetchAll( $page = 1 )
{
$qb = $this->stoneRepository->createQueryBuilder('S');
$qb->addSelect('A','P','I','C')
->leftJoin('S.attribute', 'A')
->leftJoin('A.category', 'C')
->innerJoin('S.product' , 'P')
->innerJoin('S.image' , 'I')
->where('S.state=:state')
->setParameter('state' , 1 );
$resultArray = $qb->getQuery()->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);
$paginator = new \Zend\Paginator\Paginator(new \Zend\Paginator\Adapter\ArrayAdapter($resultArray));
$paginator->setCurrentPageNumber($page);
return $paginator;
}
On the Doctrine documentation for Pagination they state to use $fetchJoinCollection = true, which I believe is the same as the HYDRATE you are trying to use.
Doctrine Pagination
On my pagination code for my QueryBuilder I use it like the following:
public function getAllPaginated($page, $limit){
$query = $this->createQueryBuilder('o')
->select('o')
->getQuery();
$paginator = new Paginator($query, $fetchJoinCollection = true);
$paginator->getQuery()
->setFirstResult($limit * ($page - 1)) // Offset
->setMaxResults($limit);
return $paginator;
}

Test class not covering method fully?

Hi i have a custom controller which clones opportunity with a new currency,clones quote and all its quote line item.A button on Quote page layout does all this.While writing a test class to cover this code,i could not cover certain lines and do not know why.The code is as follows :
CloneOppNewCurrencyController.cls :
public with sharing class CloneOppNewCurrencyController {
public List<DatedConversionRate>lstCurrencies{get;set;}
public String selectedCurrency{get;set;}
public List<SelectOption> cTypes{get;set;}
public boolean flag{get;set;}
public Date closeDate;
public String qId{get;set;}
public Quote qObj{get;set;}
public Quote qClone{get;set;}
public Opportunity oppObj;
public Opportunity oppClone{get;set;}
public List<QuoteLineItem> lstQuoteLineItems;
public List<QuoteLineItem> lstClonedQuoteLineItems;
public QuoteLineItem clonedQuoteLineItem;
public Double exchangeRate;
public Map<String,Double>mapExchangeRates;
public List<PriceBookEntry> pbe;
public List<Id>pb;
public Quote testClone{get;set;}
public Map<Id,PricebookEntry>mapProIdNpBookEntry;
public List<Renewed_Entitlement__c> lstRE;
public List<Quoted_Asset__c> lstQuotedAsset;
public Renewed_Entitlement__c cloneRE;
public Quoted_Asset__c cloneQA;
//Constructor
public CloneOppNewCurrencyController() {
pb = new List<Id>();
lstRE = new List<Renewed_Entitlement__c>();
lstQuotedAsset = new List<Quoted_Asset__c>();
lstclonedQuoteLineItems = new List<QuoteLineItem>();
mapProIdNpBookEntry = new Map<Id,PriceBookEntry>();
//get quote Id from Page
qId=Apexpages.currentPage().getParameters().get('id');
//Get the Opp Id
qObj=[Select q.Total_Price__c, q.Total_Margin__c, q.Total_Cost__c, q.TotalPrice, q.Tax, q.SystemModstamp, q.Subtotal,
q.Status, q.Siebel_Id__c, q.ShippingStreet, q.ShippingState, q.ShippingPostalCode, q.ShippingName, q.ShippingHandling,
q.ShippingCountry, q.ShippingCity, q.Revision_Number__c, q.Quote_Expiry__c, q.Quote_Date__c, q.QuoteToStreet,
q.QuoteToState, q.QuoteToPostalCode, q.QuoteToName, q.QuoteToCountry, q.QuoteToCity, q.QuoteNumber, q.Pricebook2Id,
q.Price_Book__c, q.Phone, q.Opportunity.Id, q.OpportunityId, q.Name, q.LineItemCount, q.LastModifiedDate,
q.LastModifiedById, q.IsSyncing, q.IsDeleted, q.Internal_Notes__c, q.Id, q.GrandTotal, q.Fax, q.Email, q.Discount,
q.Description, q.Default_Payment_Terms__c, q.Customer_Comments__c, q.CurrencyIsoCode, q.CreatedDate, q.CreatedById,
q.ContactId, q.BillingStreet, q.BillingState, q.BillingPostalCode, q.BillingName, q.BillingCountry, q.BillingCity, q.Opportunity.CloseDate,
q.AdditionalStreet, q.AdditionalState, q.AdditionalPostalCode, q.AdditionalName, q.AdditionalCountry, q.AdditionalCity,
q.Account_Number__c, q.Account_Manager__c, q.Account_Manager_Phone__c, q.Account_Manager_Fax__c, q.Account_Manager_Email__c ,
q.Pricebook2.Organisation__c, q.Pricebook2.External_Id__c, q.Pricebook2.IsStandard, q.Pricebook2.Description, q.Pricebook2.IsActive,
q.Pricebook2.CurrencyIsoCode, q.Pricebook2.Name
From Quote q
where q.Id =:qId];
closeDate = qObj.Opportunity.CloseDate;
cTypes=new List<SelectOption>();
mapExchangeRates = new Map<String,Double>();
cTypes.add(new SelectOption('None','None'));
for(DatedConversionRate d:[Select StartDate, NextStartDate, IsoCode, Id, ConversionRate From DatedConversionRate where StartDate<=:closeDate and NextStartDate >=:closeDate]){
cTypes.add(new SelectOption(d.IsoCode,d.IsoCode));
mapExchangeRates.put(d.IsoCode,d.ConversionRate);
}
//query all fields in Opp which has this quote to clone it
oppObj = [Select o.X18_Character_Id__c, o.Win_Loss_Reason_Details__c, o.Win_Loss_Cancelled_Reason__c, o.Where_is_A_End__c,
o.Upload_Date_Time__c, o.Type, o.Total_Price__c, o.Total_Margin_in_Account_Currency__c, o.Total_Margin__c,
o.Total_Cost__c, o.Timescale__c, o.Technology_Margin__c, o.SystemModstamp, o.SyncedQuoteId, o.Suspended__c,
o.Start_of_Close_Date_FY__c, o.Start_of_Close_Date_FY_2__c, o.Start_of_Close_Date_FY_1__c, o.StageName,
o.Solution_Type__c, o.Solution_Description__c, o.Signed_SOW_Received__c, o.Siebel_Id__c, o.Service_Start_Date__c,
o.SecureCall_Margin__c, o.Salesforce_Opportunity_Id__c, o.Risk_Level__c, o.Regional_Contact_for_SFOne__c,
o.RecordTypeId, o.RFSDate__c, o.Probability, o.Primary_Competitor__c, o.Pricebook2Id, o.PS_Margin__c,
o.PO_Number__c, o.Owner_Affiliates__c, o.OwnerId, o.Other_Margin__c, o.Organisation__c,
o.OpenAir_Project_Reference__c, o.Number_of_Line_items__c, o.Non_Portfolio__c, o.NextStep, o.Need__c,
o.Name, o.NTT_Service_Family_Name__c, o.Maintenance_Margin__c, o.MSS_Margin__c, o.Lost_to__c, o.LeadSource,
o.Last_Update_Date_of_Phase__c, o.LastModifiedDate, o.LastModifiedById, o.LastActivityDate, o.Large_Deal__c,
o.IsWon, o.IsDeleted, o.IsClosed, o.Id, o.HasOpportunityLineItem, o.Group_Collaborator_s_Name__c,
o.ForecastCategoryName, o.ForecastCategory, o.FiscalYear, o.FiscalQuarter, o.Fiscal, o.ExpectedRevenue,
o.End_Customer__c, o.Description, o.CurrencyIsoCode, o.CreatedDate, o.CreatedById, o.Contract_Term__c,
o.Collaborate_with__c, o.Closed_Won_Status__c, o.Close_Date_this_FY__c, o.Close_Date_Last_FY__c, o.Pricebook2.CurrencyIsoCode,
o.CloseDate, o.CampaignId, o.Budget__c, o.Authority__c, o.Approval_Status__c, o.Amount, o.Account_Owner_Id__c, o.Pricebook2.IsActive,
o.Pricebook2.Organisation__c, o.Pricebook2.External_Id__c, o.Pricebook2.IsStandard, o.Pricebook2.Description, o.Pricebook2.Name ,
o.Account_Currency__c, o.AccountId, o.A_End_or_B_End_or_C_End__c
From Opportunity o
where o.Id =: qObj.OpportunityId];
lstQuoteLineItems = [Select q.Vendor_Cost_Name__c, q.UnitPrice, q.Total_Price__c, q.Total_Exchanged_Cost__c, q.Takeover_PPP__c, q.SystemModstamp,
q.Subtotal_Price__c, q.Subtotal, q.SortOrder, q.Single_Creation__c, q.Siebel_Id__c, q.Service_Start_Date__c,
q.Service_End_Date__c, q.Service_Calendar_Business_Hours__c, q.ServiceDate, q.Requested_Ship_Date__c, q.Renewed_Entitlement__c,
q.Renewal_Product__c, q.QuoteId, q.Quantity, q.PricebookEntryId, q.Price__c, q.Organisation__c, q.ListPrice, q.Line_No__c,
q.LineNumber, q.LastModifiedDate, q.LastModifiedById, q.IsDeleted, q.Install_Post_Code__c, q.Install_County_State__c,
q.Install_Country__c, q.Install_Contact__c, q.Install_City__c, q.Id, q.Exchanged_Cost__c, q.Exchange_Rate__c,
q.Discount__c, q.Discount, q.Description, q.Customer_Note__c, q.CurrencyIsoCode, q.CreatedDate, q.CreatedById,
q.Covered_Product__c, q.Covered_Asset__c, q.Cost__c, q.Cost_Price_Original__c, q.Cost_Exchange_Date__c,
q.Cost_Currency__c, q.Consolidated_Entitlement__c, q.Comments__c, q.Asset_Expires__c, q.Address_2__c, q.Vendor_RRP__c,
q.PricebookEntry.IsDeleted, q.PricebookEntry.ProductCode, q.PricebookEntry.SystemModstamp, q.PricebookEntry.LastModifiedById,
q.PricebookEntry.LastModifiedDate, q.PricebookEntry.CreatedById, q.PricebookEntry.CreatedDate, q.PricebookEntry.UseStandardPrice,
q.PricebookEntry.IsActive, q.PricebookEntry.UnitPrice, q.PricebookEntry.CurrencyIsoCode, q.PricebookEntry.Product2Id,
q.PricebookEntry.Pricebook2Id, q.PricebookEntry.Name, q.PricebookEntry.Id,
q.Address_1__c From QuoteLineItem q
where q.QuoteId =:qObj.Id];
for(QuoteLineItem oLineItem : lstQuoteLineItems) {
pb.add(oLineItem.PricebookEntry.Product2Id);
}
//query renewal entitlements under the query to clone it
lstRE = [Select r.Quote__c, r.Quote_Status__c, r.Quote_Line_Item__c, r.Opportunity__c, r.Name, r.Id, r.Entitlement__c,
r.Entitlement_Start_Date__c, r.Entitlement_Service_Calendar__c, r.Entitlement_Part_Code__c, r.Entitlement_End_Date__c,
r.CurrencyIsoCode
From Renewed_Entitlement__c r
where r.Quote__c =:qId ];
//query quoted assets under the query to clone it
lstQuotedAsset = [Select q.Quote__c, q.Name, q.Id, q.CurrencyIsoCode, q.Asset__c
From Quoted_Asset__c q
where q.Quote__c =:qId];
}
public void proceed() {
try {
if(selectedCurrency == 'None' || selectedCurrency == '') {
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'Please select a currency in order to proceed'));
}
pbe = [Select p.UnitPrice, p.Product2Id, p.Pricebook2Id, p.Name, p.IsActive, p.Id, p.CurrencyIsoCode From PricebookEntry p
where p.CurrencyIsoCode =:selectedCurrency and p.Pricebook2Id =:oppObj.Pricebook2Id and p.Product2Id in :pb];
for(PricebookEntry pbe : pbe) {
mapProIdNpBookEntry.put(pbe.Product2Id,pbe);
}
for(QuoteLineItem oLine:lstQuoteLineItems) {
if(!mapProIdNpBookEntry.containsKey(oLine.PricebookEntry.Product2Id)) {
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'No pricebook entry exists for this particular currency.Hence kindly create an entry with the selected currency before cloning Opportunity.'));
return;
}
}
if(selectedCurrency!='None') {
if(oppObj.StageName!='Qualification') {
oppClone = oppObj.clone(false,true);
oppClone.ForecastCategoryName = 'Omitted';
oppClone.CurrencyIsoCode = selectedCurrency;
System.debug('Pricebook2Id::::' +oppClone.Pricebook2Id);
oppClone.Pricebook2Id = oppObj.Pricebook2Id;
oppClone.Name = selectedCurrency + oppObj.Name;
Database.insert(oppClone);
System.debug('Inserted Opp Currency >>> ' + oppClone.CurrencyIsoCode);
if(qObj.IsSyncing != true) {
qClone = qObj.clone();
qClone.Name = selectedCurrency + qObj.Name;
qClone.OpportunityId = oppClone.Id;
Database.insert(qClone);
System.debug('Inserted Quote Currency >>> ' + qClone.CurrencyIsoCode);
testClone= [SELECT Id, CurrencyIsoCode FROM Quote WHERE ID=:qClone.Id];
oppClone.SyncedQuoteId = qClone.Id;
}
else {
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'Synced Quote cannot be cloned.Please stop sync before cloning'));
}
Database.update(oppClone);
System.debug('Inserted Quote Currency >>> ' + testClone.CurrencyIsoCode);
}
if((lstRE!=null || !(lstRE.isEmpty())) && qClone.Id !=null) {
for(Renewed_Entitlement__c re:lstRE) {
cloneRE = new Renewed_Entitlement__c();
cloneRE = re.clone();
cloneRE.Quote__c = qClone.Id;
Database.insert(cloneRE);
}
}
if((lstQuotedAsset!=null || !(lstQuotedAsset.isEmpty())) && qClone.Id !=null) {
for(Quoted_Asset__c qa:lstQuotedAsset) {
cloneQA = new Quoted_Asset__c();
cloneQA = qa.clone();
cloneQA.Quote__c = qClone.Id;
Database.insert(cloneQA);
}
}
System.debug('^^^aaa^^^^^^^^'+mapProIdNpBookEntry);
if(qClone!=null) {
if(lstQuoteLineItems!=null) { System.debug('not null line items');//tbd
for(QuoteLineItem oLine:lstQuoteLineItems) {
clonedQuoteLineItem = new QuoteLineItem();
clonedQuoteLineItem = oLine.clone();
system.debug('^^12111111' + oLine.PricebookEntry.Product2Id);
if(mapProIdNpBookEntry.containsKey(oLine.PricebookEntry.Product2Id)) {
clonedQuoteLineItem.PricebookEntryId=mapProIdNpBookEntry.get(oLine.PricebookEntry.Product2Id).Id;
}
clonedQuoteLineItem.QuoteId = qClone.Id;
System.debug('Quote line Iso Code'+clonedQuoteLineItem.CurrencyIsoCode);
//update price,margin and vendors
if(mapExchangeRates.containsKey(selectedCurrency)) { System.debug('$$$containsKey iruku$$$'+'###value is###'+mapExchangeRates.get(selectedCurrency));
if(oLine.Price__c!=null && mapExchangeRates.get(selectedCurrency)!=0) {
clonedQuoteLineItem.Price__c = oLine.Price__c / mapExchangeRates.get(clonedQuoteLineItem.CurrencyIsoCode);
}
if(oLine.UnitPrice != null && mapExchangeRates.get(selectedCurrency)!=0) {
clonedQuoteLineItem.UnitPrice = oLine.UnitPrice / mapExchangeRates.get(clonedQuoteLineItem.CurrencyIsoCode);
}
if(oLine.Vendor_RRP__c != null && mapExchangeRates.get(selectedCurrency)!=0) {
clonedQuoteLineItem.Vendor_RRP__c = oLine.Vendor_RRP__c / mapExchangeRates.get(clonedQuoteLineItem.CurrencyIsoCode);
}
}
lstclonedQuoteLineItems.add(clonedQuoteLineItem);
}
System.debug(' >>> ' + lstclonedQuoteLineItems);
if(lstclonedQuoteLineItems.size()>0) {
insert lstclonedQuoteLineItems;
}
}
}
}
}catch(Exception e) {
}
}
public pageReference cancel() {
return null;
}
}
testCloneNewCurrencyController.cls
#isTest(SeeALLData=true)
private class testCloneNewCurrencyController {
static testMethod void myUnitTest() {
// TO DO: implement unit test
Account account=new Account(Name='Test');
insert account;
Contact cn=new Contact(Accountid=account.id);
cn.LastName='test';
insert cn;
// set up opportunity name and price book id
String opportunityName = 'My Opportunity';
String standardPriceBookId = '';
PriceBook2 pb2Standard = [select Id from Pricebook2 where isStandard=true];
standardPriceBookId = pb2Standard.Id;
// set up opp and Verify that the results are as expected.
Opportunity o = new Opportunity(AccountId=account.Id, Name=opportunityName,
StageName='Prospecting', CloseDate=Date.today(),Contract_Term__c = 6);
insert o;
Opportunity opp = [SELECT Name FROM Opportunity WHERE Id = :o.Id];
System.assertEquals(opportunityName, opp.Name);
// set up product2 and Verify that the results are as expected.
Product2 p2 = new Product2(Name='Test Product',isActive=true,Product_Code_Upload__c = 'Test Product 1' , ProductCode = 'Test Product 1');
insert p2;
Product2 p2ex = [SELECT Name FROM Product2 WHERE Id = :p2.Id];
System.assertEquals('Test Product', p2ex.Name);
// set up PricebookEntry and Verify that the results are as expected.
PricebookEntry pbe = new PricebookEntry(Pricebook2Id=standardPriceBookId, Product2Id=p2.Id, UnitPrice=99, isActive=true );
insert pbe;
PricebookEntry pbeex = [SELECT Pricebook2Id FROM PricebookEntry WHERE Id = :pbe.Id];
System.assertEquals(standardPriceBookId, pbeex.Pricebook2Id);
// set up OpportunityLineItem and Verify that the results are as expected.
OpportunityLineItem oli = new OpportunityLineItem(PriceBookEntryId=pbe.Id, OpportunityId=o.Id, Quantity=1, UnitPrice=99 , Cost_Currency__c = 'USD',Cost__c=2000);
insert oli;
OpportunityLineItem oliex = [SELECT PriceBookEntryId FROM OpportunityLineItem WHERE Id = :oli.Id];
oli.Cost_Currency__C = 'GBP';
update oli;
update account;
Quote quot1 = new Quote(Name='Quote1',OpportunityId=o.Id,Pricebook2Id=standardPriceBookId);
insert quot1;
// set up OpportunityLineItem and Verify that the results are as expected.
QuoteLineItem qli = new QuoteLineItem(QuoteId = quot1.Id,PriceBookEntryId=pbe.Id,UnitPrice=1000, Quantity=1, Price__c=3500 , Cost_Currency__c = 'USD',Cost__c=2000);
insert qli;
// Create two Asset records and relate them to the oli through Ordered Asset records
Asset ass1 = new Asset(Name='Asset1',SerialNumber='12345',AccountId=account.Id,ContactId=cn.Id);
insert ass1;
Asset ass2 = new Asset(Name='Asset1',SerialNumber='678910',AccountId=account.Id,ContactId=cn.Id);
insert ass2;
Quoted_Asset__c ordass1 = new Quoted_Asset__c(Asset__c=ass1.Id,Quote_Line_Item__c=qli.Id,Quote__c=quot1.Id);
insert ordass1;
Quoted_Asset__c ordass2 = new Quoted_Asset__c(Asset__c=ass2.Id,Quote_Line_Item__c=qli.Id,Quote__c=quot1.Id);
insert ordass2;
// Check that the Serial numbers field on the QLI is as expected
QuoteLineItem quot1test = [SELECT LineNumber, Serial_Numbers__c FROM QuoteLineItem WHERE Id =: qli.Id];
Test.startTest();
Test.setCurrentPage(new Pagereference('/apex/CloneOppNewCurrency?id='+quot1.Id));
CloneOppNewCurrencyController c = new CloneOppNewCurrencyController();
c.selectedCurrency = 'USD';
system.assertEquals(c.selectedCurrency, 'USD');
//c.qObj = quot1;
c.proceed();
c.selectedCurrency = 'USD';
System.debug('%%%%%'+c.oppClone+'$$$$$'+c.selectedCurrency+'Opp OBj is:'+c.oppObj);
Test.setCurrentPage(new Pagereference('/apex/CloneOppNewCurrency?id='+quot1.Id));
CloneOppNewCurrencyController c1 = new CloneOppNewCurrencyController();
c1.selectedCurrency = 'None';
Pagereference pr = c1.cancel();
Test.stopTest();
}
}
Lines from 127 are not covered.The proceed method is not covered.Can anyone help me please?
What line does 127 correspond to in your example? Is it if(selectedCurrency!='None') { in the proceed() method?
I'd suggest to extend your exception handling. You basically have:
public void proceed() {
try {
// Most of method body here
} catch(Exception e) {
}
}
It is likely that an exception has occured and has been ignored/lost due to the empty Exception handling. Minimally, write the exception out to the log:
} catch(Exception e) {
System.debug(LoggingLevel.Error, 'BANG! ' + e);
}
That may well reveal in the debug log where your test method is failing.

Symfony2 Doctrine2 : querybuilder bad query

New to Symfony2 and Doctrine2, i have a function in my entity repository to search entities after form submission. Input is array $get that contain form fields like $get['name'] = 'aname'.
My problem is that when i request with an id, or an id and a name, it's ok by with only a name, all my entities are matched because the query that has been build have no where clause.
Here is my code :
public function search(array $get, $flag = False){
/* Indexed column (used for fast and accurate table cardinality) */
$alias = 'd';
/* DB table to use */
$tableObjectName = 'mysiteMyBundle:DB';
$qb = $this->getEntityManager()
->getRepository($tableObjectName)
->createQueryBuilder($alias)
->select($alias.'.id');
$arr = array();
//Simple array, will grow after problem solved
$numericFields = array(
'id');
$textFields = array(
'name');
while($el = current($get)) {
$field = key($get);
if ( $field == '' or $field == Null or $el == '' or $el == Null ) {
next($get);
}
if ( in_array($field,$numericFields) ){
if ( is_numeric($el) ){
$arr[] = $qb->expr()->eq($alias.".".$field, $el);
}
} else {
if ( in_array($field,$textFields) ) {
$arr[] = $qb->expr()->like($alias.".".$field, $qb->expr()->literal('%'.$el.'%') );
}
}
next($get);
}
if(count($arr) > 0) $qb->andWhere(new Expr\Orx($arr));
else unset($arr);
$query = $qb->getQuery();
if($flag)
return $query;
else
return $query->getResult();
}
The query generated with only a name (ex "myname") input is :
SELECT d0_.id AS id0 FROM DB d0_
It should be:
SELECT d0_.id AS id0 FROM DB d0_ WHERE d0_.name LIKE '%myname%'
What's wrong with my code ?
Thanks !
I don't know if it's related, but do not use "OR" or "AND" operators, because they have a different meaning that the classic "&&" or "||". cf http://php.net/manual/en/language.operators.logical.php
So, first, replace "AND" by "&&", and "OR" by "||".
you should use the setParameter method
$query->where('id = :id')->setParameter('id', $id);

Return number of results from Doctrine query that uses createQuery

$q = $this->_em->createQuery("SELECT s FROM app\models\Quest s
LEFT JOIN s.que c
WHERE s.type = '$sub'
AND c.id = '$id'");
Given a query like the one above, how would I retrieve the number of results?
Alternatively one can look at what Doctrine Paginator class does to a Query object to get a count (this aproach is most probably an overkill though, but it answers your question):
public function count()
{
if ($this->count === null) {
/* #var $countQuery Query */
$countQuery = $this->cloneQuery($this->query);
if ( ! $countQuery->getHint(CountWalker::HINT_DISTINCT)) {
$countQuery->setHint(CountWalker::HINT_DISTINCT, true);
}
if ($this->useOutputWalker($countQuery)) {
$platform = $countQuery->getEntityManager()->getConnection()->getDatabasePlatform(); // law of demeter win
$rsm = new ResultSetMapping();
$rsm->addScalarResult($platform->getSQLResultCasing('dctrn_count'), 'count');
$countQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\CountOutputWalker');
$countQuery->setResultSetMapping($rsm);
} else {
$countQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Doctrine\ORM\Tools\Pagination\CountWalker'));
}
$countQuery->setFirstResult(null)->setMaxResults(null);
try {
$data = $countQuery->getScalarResult();
$data = array_map('current', $data);
$this->count = array_sum($data);
} catch(NoResultException $e) {
$this->count = 0;
}
}
return $this->count;
}
You can either perform a count query beforehand:
$count = $em->createQuery('SELECT count(s) FROM app\models\Quest s
LEFT JOIN s.que c
WHERE s.type=:type
AND c.id=:id)
->setParameter('type', $sub);
->setParameter('id', $id);
->getSingleScalarResult();
Or you can just execute your query and get the size of the results array:
$quests = $q->getResult();
$count = count($quests);
Use the first method if you need the count so that you can make a decision before actually retrieving the objects.