Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions moxygen/main/default/classes/database/MockDatabaseTest.cls
Original file line number Diff line number Diff line change
Expand Up @@ -7505,4 +7505,32 @@ private class MockDatabaseTest {
'Incorrect number of opportunities'
);
}

@isTest
static void ensureNextNMonthsWorksInWhereClause() {
List<Opportunity> oppList = new List<Opportunity>();
Date startOfMonth = Gmt.today().toStartOfMonth();
for (Integer i = 0; i < 12; i++) {
oppList.add(
new Opportunity(
Name = 'Opp' + i,
CloseDate = startOfMonth.addMonths(i)
)
);
}

MockDatabase.doInsert(oppList, true);

Test.startTest();
List<Opportunity> opportunities = MockDatabase.query(
'SELECT Id, CloseDate FROM Opportunity WHERE CloseDate = NEXT_N_MONTHS:6'
);
Test.stopTest();

Assert.areEqual(
6,
opportunities.size(),
'Incorrect number of opportunities'
);
}
}
4 changes: 3 additions & 1 deletion moxygen/main/default/classes/database/Token.cls
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ public with sharing class Token {
public final static String NEXT_N_YEARS_LITERAL = 'next_n_years';
public final static String LAST_N_QUARTERS_LITERAL = 'last_n_quarters';
public final static String N_WEEKS_AGO_LITERAL = 'n_weeks_ago';
public final static String NEXT_N_MONTHS_LITERAL = 'next_n_months';

public final static Set<String> DATE_LITERAL_TOKENS = new Set<String>{
TODAY_LITERAL,
Expand Down Expand Up @@ -204,6 +205,7 @@ public with sharing class Token {
LAST_YEAR_LITERAL,
NEXT_N_YEARS_LITERAL,
LAST_N_QUARTERS_LITERAL,
N_WEEKS_AGO_LITERAL
N_WEEKS_AGO_LITERAL,
NEXT_N_MONTHS_LITERAL
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ public with sharing class DateLiteralComparableFactory {
Token.NEXT_N_YEARS_LITERAL => NextNYearsComparable.class,
Token.LAST_N_QUARTERS_LITERAL => LastNQuartersComparable.class,
Token.N_QUARTERS_AGO_LITERAL => NQuartersAgoComparable.class,
Token.N_WEEKS_AGO_LITERAL => NWeeksAgoComparable.class
Token.N_WEEKS_AGO_LITERAL => NWeeksAgoComparable.class,
Token.NEXT_N_MONTHS_LITERAL => NextNMonthsComparable.class
};

@TestVisible
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* @description Compares a date to N months in the future
* @author Zackary Frazier
* @since 2/12/2025
* @group Soql Engine
*/
public with sharing class NextNMonthsComparable extends DateLiteralComparable {
public override Boolean isLessThan(Datetime fieldValue) {
Date startOfNextMonth = Gmt.today().toStartOfMonth().addMonths(1);
return fieldValue < startOfNextMonth;
}

public override Boolean isGreaterThan(Datetime fieldValue) {
Date endOfNextNMonths = Gmt.today().toStartOfMonth().addMonths(this.n);
return fieldValue >= endOfNextNMonths.addMonths(1);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>62.0</apiVersion>
<status>Active</status>
</ApexClass>
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
@isTest
private class NextNMonthsComparableTest {
@isTest
static void ensureIsLessThanWorks() {
DateLiteralComparable nextNMonthsComparable = new NextNMonthsComparable()
.withToken('next_n_months:1');

Date startOfThisMonth = Gmt.today().toStartOfMonth();
Date startOfNextMonth = startOfThisMonth.addMonths(1);
Date startOfMonthAfterNext = startOfNextMonth.addMonths(1);

Assert.isTrue(
nextNMonthsComparable.isLessThan(startOfThisMonth),
'Should be less than'
);
Assert.isFalse(
nextNMonthsComparable.isLessThan(startOfNextMonth),
'Should not be less than'
);
Assert.isFalse(
nextNMonthsComparable.isLessThan(startOfMonthAfterNext),
'Should not be less than'
);
}

@isTest
static void ensureIsGreaterThanWorks() {
DateLiteralComparable nextNMonthsComparable = new NextNMonthsComparable()
.withToken('next_n_months:1');

Date startOfThisMonth = Gmt.today().toStartOfMonth();
Date startOfNextMonth = startOfThisMonth.addMonths(1);
Date startOfMonthAfterNext = startOfNextMonth.addMonths(1);

Assert.isFalse(
nextNMonthsComparable.isGreaterThan(startOfThisMonth),
'Should not be greater than'
);
Assert.isFalse(
nextNMonthsComparable.isGreaterThan(startOfNextMonth),
'Should not be greater than'
);
Assert.isTrue(
nextNMonthsComparable.isGreaterThan(startOfMonthAfterNext),
'Should be greater than'
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>62.0</apiVersion>
<status>Active</status>
</ApexClass>
Original file line number Diff line number Diff line change
Expand Up @@ -932,4 +932,22 @@ private class ParserTest {
}
Test.stopTest();
}

@isTest
static void ensureNextNMonthsCanBeParsed() {
Parser p = new Parser();
String soqlQuery = 'SELECT Id FROM Opportunity WHERE CreatedDate = NEXT_N_MONTHS:6';
Test.startTest();
try {
p.parse(soqlQuery);
} catch (Exception e) {
Assert.fail(
'Expected no exception but got ' +
e.getMessage() +
' for ' +
soqlQuery
);
}
Test.stopTest();
}
}