Kotlin: how to combine certain data in list - list

I want to process the crossday data(id = 1 and 2 or 3 and 4) with endTime and startTime in list, but some data were not crossday..... how would you approach this?
I already process to get data by this code.
val grouped = oldListNewSleepData
.groupBy { it.startTime }
.flatMap { entry ->
Timber.i("get sleep entry: $entry")
listOf(
NewSleepData(id = entry.value.first().id,
startTime = entry.key ,
endTime = entry.value.maxBy { item -> item.endTime!!}?.endTime,
duration = entry.value.first { item -> item.duration != null }.duration,
activity = entry.value.first { item -> item.activity != null }.activity
)
)
}
.filter {
it.activity != null &&
(it.activity.contains("Sleep") || it.activity.contains("Awake"))
}
this is data
[
NewSleepData(id=1, startTime=2020-05-07T23:30:00.000Z, endTime=2020-05-08T00:00:00.000Z, activity=Sleep, duration=0.50),
NewSleepData(id=2, startTime=2020-05-08T00:00:00.000Z, endTime=2020-05-08T08:30:00.000Z, activity=Sleep, duration=8.50),
//// merge above startTime and endTime
NewSleepData(id=3, startTime=2020-05-09T22:47:00.000Z, endTime=2020-05-10T00:00:00.000Z, activity=Sleep, duration=1.22),
NewSleepData(id=4, startTime=2020-05-10T00:00:00.000Z, endTime=2020-05-10T08:43:00.000Z, activity=Sleep, duration=8.72),
//// merge above startTime and endTime
NewSleepData(id=5, startTime=2020-05-11T00:50:00.000Z, endTime=2020-05-11T08:30:00.000Z, activity=Sleep, duration=7.67),
NewSleepData(id=6, startTime=2020-05-12T01:00:00.000Z, endTime=2020-05-12T08:03:00.000Z, activity=Sleep, duration=7.05),
NewSleepData(id=7, startTime=2020-05-13T01:00:00.000Z, endTime=2020-05-13T07:55:00.000Z, activity=Sleep, duration=6.92),
NewSleepData(id=8, startTime=2020-05-13T15:00:00.000Z, endTime=2020-05-13T16:01:00.000Z, activity=LightSleep, duration=1.02),
NewSleepData(id=9, startTime=2020-05-14T01:56:00.000Z, endTime=2020-05-14T08:29:00.000Z, activity=LightSleep, duration=4.22),
NewSleepData(id=9, startTime=2020-05-14T02:05:00.000Z, endTime=2020-05-14T07:49:00.000Z, activity=DeepSleep, duration=1.53),
NewSleepData(id=9, startTime=2020-05-14T06:10:00.000Z, endTime=2020-05-14T06:58:00.000Z, activity=Awake(during sleep cycle), duration=0.80),
NewSleepData(id=10, startTime=2020-05-15T02:07:00.000Z, endTime=2020-05-15T08:24:00.000Z, activity=LightSleep, duration=4.58),
NewSleepData(id=10, startTime=2020-05-15T02:16:00.000Z, endTime=2020-05-15T07:47:00.000Z, activity=DeepSleep, duration=1.70)
]
*Update
Sorry, I want to get this
[
NewSleepData(id=1, startTime=2020-05-07T23:30:00.000Z, endTime=2020-05-08T08:30:00.000Z, activity=Sleep, duration=9.00)
NewSleepData(id=3, startTime=2020-05-09T22:47:00.000Z, endTime=2020-05-10T08:43:00.000Z, activity=Sleep, duration=9.94)
NewSleepData(id=5, startTime=2020-05-11T00:50:00.000Z, endTime=2020-05-11T08:30:00.000Z, activity=Sleep, duration=7.67),
NewSleepData(id=6, startTime=2020-05-12T01:00:00.000Z, endTime=2020-05-12T08:03:00.000Z, activity=Sleep, duration=7.05),
NewSleepData(id=7, startTime=2020-05-13T01:00:00.000Z, endTime=2020-05-13T07:55:00.000Z, activity=Sleep, duration=6.92),
NewSleepData(id=8, startTime=2020-05-13T15:00:00.000Z, endTime=2020-05-13T16:01:00.000Z, activity=LightSleep, duration=1.02),
NewSleepData(id=9, startTime=2020-05-14T01:56:00.000Z, endTime=2020-05-14T08:29:00.000Z, activity=LightSleep, duration=4.22),
NewSleepData(id=9, startTime=2020-05-14T02:05:00.000Z, endTime=2020-05-14T07:49:00.000Z, activity=DeepSleep, duration=1.53),
NewSleepData(id=9, startTime=2020-05-14T06:10:00.000Z, endTime=2020-05-14T06:58:00.000Z, activity=Awake(during sleep cycle), duration=0.80),
NewSleepData(id=10, startTime=2020-05-15T02:07:00.000Z, endTime=2020-05-15T08:24:00.000Z, activity=LightSleep, duration=4.58),
NewSleepData(id=10, startTime=2020-05-15T02:16:00.000Z, endTime=2020-05-15T07:47:00.000Z, activity=DeepSleep, duration=1.70)
]

Related

Performance Issue when retrieving transaction details from Quorum Blockchain

I have experienced performance issue when retrieving transaction details such as transaction originator and transaction recipient
from the Quorum blockchain.
The Javascript For loop and Web3.eth.contract(abi).at(address2).totalTransactions is used to retrieve transaction details and
then append to HTML table.
My performance problem is that the retrieval of few lines of transaction data from Quorum blockchain takes about 30 seconds.
Moreover, I am using web3-quorum#0.1.1 and quorum-js#0.3.0.
$('#get-tran').click(() => {
// Get Tran History
var tranId = 0;
let w2Contract=web3w2.eth.contract(abi).at(address2);
let tottr = w2Contract.totalTransactions();
//Clear the old table content first
$("#t02 tr").remove();
var i=0;
for (i = 0; i <= w2Contract.totalTransactions()-1; i++) {
tranId = i;
let tranHash = w2Contract.transactionIDs(i);
let trDetails1 = w2Contract.transactions(tranHash);
console.log(`Tran details ${trDetails1}`);
console.log(`Tran Detail 1: ${trDetails1[1]}`);
console.log(`Tran Detail 2: ${trDetails1[2]}`);
console.log(`Tran Detail 0: ${trDetails1[0]}`);
var tableRef = document.getElementById('t02').getElementsByTagName('tbody')[0];
// Insert a row at the end of the table
let newRow = tableRef.insertRow(-1);
// Insert a cell in the row at index 0
let newCell = newRow.insertCell(0);
// Append a text node to the cell
let newText = document.createTextNode(`${tranId}`);
newCell.appendChild(newText);
// Insert a cell in the row at index 1
let newCell1 = newRow.insertCell(1);
// Append a text node to the cell
let newText1 = document.createTextNode(`${trDetails1[1]}`);
console.log(`newText1 at index 1 ${newText1}`);
// w2 > w1
if ((trDetails1[1] == '0xf9a2cb34b6b5fd7a2ac0c2e9b2b9406d6daffbd4') &&
(trDetails1[2] == '0x180893a0ec847fa8c92786791348d7d65916acbb')) {
newText1.textContent = 'Stock In'
} else if
(trDetails1[1] == '0x180893a0ec847fa8c92786791348d7d65916acbb') {
newText1.textContent = 'Pier Company'
} else if (trDetails1[1] == '0xf9a2cb34b6b5fd7a2ac0c2e9b2b9406d6daffbd4') {
newText1.textContent = 'Warehouse Company'
}
newCell1.appendChild(newText1);
// Insert a cell in the row at index 2
let newCell2 = newRow.insertCell(2);
// Append a text node to the cell
let newText2 = document.createTextNode(`${trDetails1[2]}`);
console.log(`newText1 at index 2 ${newText1}`);
if (trDetails1[2] == '0xf9a2cb34b6b5fd7a2ac0c2e9b2b9406d6daffbd4') {
newText2.textContent = 'Warehouse Company'
}
if (trDetails1[2] == '0x180893a0ec847fa8c92786791348d7d65916acbb') {
newText2.textContent = 'Pier Company'
}
if (trDetails1[2] == '0xc8f717ba9593dc9d45c4518cf444d2cbd08af24d') {
newText2.textContent = 'Removal'
}
newCell2.appendChild(newText2);
// Insert a cell in the row at index 3
let newCell3 = newRow.insertCell(3);
// Append a text node to the cell
let newText3 = document.createTextNode(`${trDetails1[0]}`);
console.log(`newText3 at index 3 ${newText3}`);
newCell3.appendChild(newText3);
// Insert a cell in the row at index 4
let newCell4 = newRow.insertCell(4);
// Append a text node to the cell
let newText4 = document.createTextNode(`${trDetails1[3]}`);
console.log(`newText1 at index 4 ${newText4}`);
if (trDetails1[3] ) {
newText4.textContent = 'Confirmed'
} else {
newText4.textContent = 'Pending'
}
newCell4.appendChild(newText4);
}
});

How to Schedule Local Notification Once in a Day at Random Time With Random Text

I Want Random Local notification once every 24 hours.
I know , i Can have Daily Local Notification Using this :
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = fireDate;
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.repeatInterval = NSDayCalendarUnit;
localNotification.alertBody = alertText;
localNotification.alertAction = alertAction;
// Schedule it with the app
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
[localNotification release];
But ,With This I can Have Same Time Every Day ,But How can I have a Random Time EveryDay.
Please Help !
Even, Is this Possible ?
According to UILocalNotification class reference you could schedule up to 64 local notifications to fire at exact time. It is enough to cover a couple months of random timed notifications since every app launch. Here is a sample:
- (void)scheduleLocalNotifications
{
[[UIApplication sharedApplication] cancelAllLocalNotifications];
static NSInteger dayInSeconds = 60*60*24;
NSInteger now = (NSInteger)[NSDate timeIntervalSinceReferenceDate];
NSInteger tomorrowStart = now - now % dayInSeconds + dayInSeconds;
for (int q=0; q<64; ++q)
{
NSInteger notificationTime = tomorrowStart + q*dayInSeconds + rand()%dayInSeconds;
NSDate * notificationDate = [NSDate dateWithTimeIntervalSinceReferenceDate:notificationTime];
NSLog(#"date %#", notificationDate);
UILocalNotification * notification = [UILocalNotification new];
notification.fireDate = notificationDate;
notification.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
notification.soundName = UILocalNotificationDefaultSoundName;
notification.alertBody = #"Hello!";
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
}
For anybody looking to do this in Swift you can do something like this:
func scheduleNotfications() {
print("Scheduling reminder notifications")
UIApplication.sharedApplication().cancelAllLocalNotifications()
let windowInSeconds: UInt32 = 60*60*5
let oneDayInSeconds: Double = 60*60*24
let windowAroundHour = 14
let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
calendar?.timeZone = NSTimeZone.localTimeZone()
if let todayAtWindowHour = calendar?.dateBySettingHour(windowAroundHour, minute: 0, second: 0, ofDate: NSDate(), options: .MatchFirst)?.timeIntervalSinceReferenceDate {
for index in 1...48 {
var notificationDate = ( todayAtWindowHour + ( Double(index) * oneDayInSeconds ) )
// either remove or add anything up to the window
if arc4random_uniform(2) == 0 {
notificationDate = notificationDate + Double(arc4random_uniform(windowInSeconds))
} else {
notificationDate = notificationDate - Double(arc4random_uniform(windowInSeconds))
}
let fireDate = NSDate(timeIntervalSinceReferenceDate: notificationDate)
let notification = UILocalNotification()
notification.alertBody = NSLocalizedString("You've received a new notification.", comment: "Notification")
notification.fireDate = fireDate
notification.timeZone = NSTimeZone.defaultTimeZone()
notification.applicationIconBadgeNumber = 1
UIApplication.sharedApplication().scheduleLocalNotification(notification)
print("Set for: \(fireDate)")
}
}
print("Finished scheduling reminder notifications")
}
The above will schedule random notifications for the next 48 days, making sure those notifications only fire at a reasonable time of the day.
You can call this from applicationDidBecomeActive()
func applicationDidBecomeActive(application: UIApplication) {
UIApplication.sharedApplication().applicationIconBadgeNumber = 0
scheduleNotfications()
}
Clean answer
This schedules a notification for the next 64 days. Good place to set it is in didFinishLaunchingWithOptions: because it cancelAllLocalNotifications and set 64 notifications for the future. So every time the user opens the app it clears and reschedule for the next 64 days from now.
[[UIApplication sharedApplication] cancelAllLocalNotifications];
NSDate *givenDate = [NSDate date]; // set your start date here
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar setTimeZone:[NSTimeZone localTimeZone]];
NSDateComponents *components = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute) fromDate:givenDate];
NSDateComponents *dateComps = [NSDateComponents new];
[dateComps setYear:components.year];
[dateComps setMonth:components.month];
[dateComps setDay:components.day];
[dateComps setHour:components.hour];
[dateComps setMinute:components.minute];
[dateComps setSecond:0];
NSDate *notificationDate = [calendar dateFromComponents:dateComps];
for (int x = 0; x < 64; x++) {
UILocalNotification *notification = [UILocalNotification new];
[notification setFireDate:notificationDate];
[notification setTimeZone:[NSTimeZone localTimeZone]];
[notification setSoundName:UILocalNotificationDefaultSoundName];
[notification setAlertBody:#"My notification body!"];
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
notificationDate = [NSDate dateWithTimeInterval:86400 sinceDate:notificationDate];
}
Output:
...
[26] Date : 2016-06-29 17:11:00 +0000
[27] Date : 2016-06-30 17:11:00 +0000
[28] Date : 2016-07-01 17:11:00 +0000
[29] Date : 2016-07-02 17:11:00 +0000
...

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.

Doctrine 2 date in where-clause (querybuilder)

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

APEX 4.1 Shuttle Null on Right

APEX version: 4.1.1.00.23
I have a shuttle that populates the right site based on what is chosen from a select list. Whenever an item is picked from the select list, the correct item or items are populated on the right panel, but there is always a null that is added. How do I get ride of the null?
Shuttle name: P51_Shuttle
Select list name: P51_Analyst
Here is my code:
HTML Header:
<script type="text/javascript">
function LoadRightPane()
{
var objDQAnalyst = document.getElementById("P51_DQ_ANALYST");
var ajaxRequest = new htmldb_Get(null,&APP_ID.,'APPLICATION_PROCESS=get_DQAttributes',0);
ajaxRequest.add('P51_DQ_ANALYST',objDQAnalyst.value);
ajaxResult = ajaxRequest.get();
//alert(ajaxResult);
if(ajaxResult)
{
var shuttleRight = document.getElementById("P51_SHUTTLE_RIGHT");
shuttleRight.options.length = 0;
var attrArray = ajaxResult.split("~colsep~");
for(var i=0; i < attrArray.length; i++) {
shuttleRight.options[i] = new Option(attrArray[i], attrArray[i]);
}
}
else
{
shuttleRight.options.length = 0;
}
ajaxRequest = null;
}
function moveitem(item) {
return;
s_left = document.getElementById("P51_SHUTTLE_TO_LEFT");
db.transaction(function(tx){
tx.executeSql('select distinct DQ_ATTRIBUTE from DQ_MANUAL_EDIT where DQ_ANALYST = ?',[item],function(tx,results)
{
for (var i=0; i < s_left.options.length;i++)
{
if (results.value == s_left.options[i].value)
{
s_left.options[i].selected = true;
g_Shuttlep_v15.move();
}
}
});
});
}
</script>
Page HTML Body Attribute:
onLoad="Javascript:LoadRightPane();"
Applicaiton/Page process called (get_DQAttributes)
DECLARE
L_RETURN VARCHAR2(2000):= NULL ;
BEGIN
BEGIN
FOR rec IN (
select distinct dq_attribute
from DQ_MANUAL_EDIT
where dq_analyst = :P51_DQ_ANALYST
)
LOOP
L_RETURN := L_RETURN || rec.dq_attribute || '~colsep~' ;
END LOOP;
end;
htp.prn(L_RETURN);
END;
Your ajax process always returns something suffixed with ~colsep~
When you run a string like that in firebug:
"test1~colsep~".split("~colsep~")
The result will be an array with 2 elements:
["test1", ""]
So your NULL element originates from that. To fix this just adjust the ajax process to trim the last separator with RTRIM.
DECLARE
L_RETURN VARCHAR2(2000):= NULL ;
BEGIN
FOR rec IN ( select distinct dq_attribute
from DQ_MANUAL_EDIT
where dq_analyst = :P51_DQ_ANALYST)
LOOP
L_RETURN := L_RETURN || rec.dq_attribute || '~colsep~' ;
END LOOP;
l_return := rtrim(l_return, '~colsep~');
htp.prn(L_RETURN);
END;
Everything about Tom's answer is correct. I had to make one modification to the line
l_return := rtrim(l_return, '~colsep~');
When running that code, the last two letters would be removed. And if I had multiple items in the shuttle, the first item would be fine, but the second one would be cut off.
For example:
Using the code: l_return := rtrim(l_return, '~colsep~');
the right panel of the shuttle would look like this
Score
Da
But the actual text should be
Score
Data
So I used the 'substr' function and now it is working
l_return := substr(l_return,0,(length(l_return)-8));
Here is the whole code
DECLARE
L_RETURN VARCHAR2(2000):= NULL ;
BEGIN
FOR rec IN ( select distinct dq_attribute
from DQ_MANUAL_EDIT
where dq_analyst = :P51_DQ_ANALYST)
LOOP
L_RETURN := L_RETURN || rec.dq_attribute || '~colsep~' ;
END LOOP;
L_RETURN := substr(l_return,0,(length(l_return)-8));
htp.prn(L_RETURN);
END;
Thank you Tom for getting my mental ball rolling!!!