filter to schedule meetings using DateTime in Genexus - genexus

I started programming a little while ago and started a project on genexus to schedule meetings for a company, which needs rules so as not to have appointments at the same times.
I made the rules using date and they were working, but when I switched to datetime they don't work anymore. I dont know Genexus syntax for that, if anyone can help with this I would appreciate it.
do case
case (LocacaoInicio <= &DTInicio and LocacaoFinal >= &DTInicio)
or (LocacaoInicio <= &DTFinal and LocacaoFinal >= &DTFinal)
&MensagemValidacao2 = 'Error'
case (LocacaoInicio >= &DTInicio and LocacaoFinal <= &DTInicio)
or (LocacaoInicio >= &DTInicio and LocacaoFinal <= &DTFinal)
&MensagemValidacao2 = 'Error'
case (LocacaoInicio < &DTFinal and LocacaoFinal < &DTFinal)
or (LocacaoInicio > &DTInicio and LocacaoFinal > &DTInicio)
&MensagemValidacao2 = 'ERROR'
case (LocacaoInicio > &DTFinal and LocacaoFinal > &DTFinal)
or (LocacaoInicio < &DTInicio and LocacaoFinal < &DTInicio)
&MensagemValidacao2 = 'Error '
endcase
translation of attributes and variables
locacaoinicio = InicialDate
locacaofinal = FinalDate
&mensagemvalidacao2 = &validationMassege
&DTFinal = &DateTimeFinal
&DTInicio = &DateTimeInicio

Related

is there a better way to write this if statement in laravel

good day i am new in laravel and i am still learning as i go.
my question is this code works but i feel like it unnecessary and can be written much better please can someone assist would a switch case be better or is there a better way to write this and please explain to me thank you.
debtorscontroller.php
$debtors_created_at = $debtors->created_at;
$now = Carbon::now();
$created_at_in_days = $debtors_created_at->diffInDays($now);
if ($created_at_in_days >= 0 and $created_at_in_days <= 10){
Debtor::whereId($debtorid)->update(['collection_level' => 'Pre Collection']);
}elseif ($created_at_in_days >= 11 and $created_at_in_days <= 30){
Debtor::whereId($debtorid)->update(['collection_level' => 'Collection Level 1']);
}
elseif ($created_at_in_days >= 31 and $created_at_in_days <= 60){
Debtor::whereId($debtorid)->update(['collection_level' => 'Collection Level 2']);
}
elseif ($created_at_in_days >= 61){
Debtor::whereId($debtorid)->update(['collection_level' => 'Collection Level 3']);
}
this just check wheter the debtor was created at and if it is 1-10 days old it changes
its level
days
1-10 is pre collection
11-30 is collection level 1
31-60 is collection level 2
61-90+ is collection level 3
this is a field in my debtors table collection_level
You can use switch statement to do the same -
$debtors = Debtor::whereId($debtorid);
$created_at_in_days = $debtors->created_at->diffInDays(Carbon::now());
switch ($created_at_in_days) {
case $created_at_in_days >= 0 and $created_at_in_days <= 10:
$debtors->update(['collection_level' => 'Pre Collection']);
break;
case $created_at_in_days >= 11 and $created_at_in_days <= 30:
$debtors->update(['collection_level' => 'Collection Level 1']);
break;
case $created_at_in_days >= 31 and $created_at_in_days <= 60:
$debtors->update(['collection_level' => 'Collection Level 2']);
break;
case $created_at_in_days >= 61:
$debtors->update(['collection_level' => 'Collection Level 3']);
break;
default:
$debtors = $debtors->get();

SWITCH with clauses differing by a constant increment

Below is my SWITCH. I want to put it in a loop. I want to constantly increase my SWITCH by 2.5, because I have a lot of different values from 0 to 1000.
Order Amount =
SWITCH (
TRUE(),
Order[Amount Order] >= 0 && Order[Amount Order] < 5 , "< 5",
Order[Amount Order] >= 5.1 && Order[Amount Order] <= 7.5, "5 - 7.5",
Order[Amount Order] >= 7.51 && Order[Amount Order] <= 10, "7.51 - 10",
Order[Amount Order] >= 10.01 && Order[Amount Order] <= 12.5, "10.01 - 12.5",
Order[Amount Order] >= 12.51 && Order[Amount Order] <= 15, "12.51 - 15",Blank())
Maybe This can help you, just let me know if it does. Thanks.
This formula succeeded for me:
Order Amount =
VAR _ceil = CEILING('Order'[Amount Order] / 2.5, 1) * 2.5
VAR _big_result = CONVERT(_ceil-2.49, STRING) & " - " & CONVERT(_ceil, STRING)
RETURN SWITCH(TRUE(),
'Order'[Amount Order] >= 0 && 'Order'[Amount Order] < 5 , "< 5",
'Order'[Amount Order] >= 5 && 'Order'[Amount Order] <= 7.5, "5 - 7.5",
_big_result)

How to group combined AND with OR statements using the Sequel GEM in Ruby?

I am fairly good at PHP (OOP & flat). And for the past year or so I have been tasked with maintaining a Ruby codebase; a skill I am still learning. I am not too clear on how to properly structure a filtering chain using Sequel so AND as well OR statements can be properly contained.
This is the MySQL query structure I want to have:
SELECT * FROM `some_objects`
WHERE (
(
((`datebegin` >= 1950) AND (`datebegin` <= 1959)) OR ((`dateend` >= 1950) AND (`dateend` <= 1959))
)
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959))
AND
(NOT `datebegin` = 0) AND (NOT `dateend` = 0)
)
;
And this is the Sequel code fragment I am using:
some_objects = where{((datebegin >= start_year) & (datebegin <= end_year)) | ((dateend >= start_year) & (dateend <= end_year))}.
or{(datebegin <= start_year) & (dateend >= end_year)}.
where(~:datebegin => 0, ~:dateend => 0)
And this is what I am actually getting:
SELECT * FROM `some_objects`
WHERE (
(
((`datebegin` >= 1950) AND (`datebegin` <= 1959)) OR ((`dateend` >= 1950) AND (`dateend` <= 1959))
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959))
)
AND
(NOT `datebegin` = 0) AND (NOT `dateend` = 0)
)
;
I have also tried different variations on the same Sequel code such as this:
some_objects = where(:datebegin => start_year..end_year).
or(:dateend => start_year..end_year).
or{|o|(o.datebegin <= start_year) & (o.dateend >= end_year)}.
where(~:datebegin => 0, ~:dateend => 0)
And this:
some_objects = where(:datebegin => start_year..end_year).
or(:dateend => start_year..end_year).
or{(datebegin <= start_year) & (dateend >= end_year)}.
where(~:datebegin => 0, ~:dateend => 0)
But I still end up with the first SQL structure where this whole chunk is basically ((AND OR AND OR)):
(
((`datebegin` >= 1950) AND (`datebegin` <= 1959)) OR ((`dateend` >= 1950) AND (`dateend` <= 1959))
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959))
)
When I want ((AND OR AND) OR):
(
((`datebegin` >= 1950) AND (`datebegin` <= 1959)) OR ((`dateend` >= 1950) AND (`dateend` <= 1959))
)
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959))
The issue with your initial query is that you are depending on the OR/AND precedence rules instead of using explicit parentheses. Your initial query could be expressed as:
SELECT * FROM `some_objects`
WHERE (
((`datebegin` >= 1950) AND (`datebegin` <= 1959))
OR
((`dateend` >= 1950) AND (`dateend` <= 1959))
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959) AND (NOT `datebegin` = 0) AND (NOT `dateend` = 0))
)
You could express this in Sequel as:
DB[:some_objects].where{((datebegin >= start_year) & (datebegin <= end_year)) | ((dateend >= start_year) & (dateend <= end_year))}.
or{((datebegin <= start_year) & (dateend >= end_year)) & Sequel.negate(:datebegin => 0)}
Which yields the following SQL:
SELECT * FROM `some_objects` WHERE (
((`datebegin` >= 1950) AND (`datebegin` <= 1959))
OR
((`dateend` >= 1950) AND (`dateend` <= 1959))
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959) AND (`datebegin` != 0))
)
This should perform the same as the SQL you used, but it is a bit more readable (e.g. datebegin != 0 instead of NOT datebegin = 0). Note that you don't need the NOT dateend = 0 filter, because it is a subset of the dateend >= 1959 filter.
Remember with Sequel if you're really up against the wall, just spell out your conditions the hard way:
records = where(%Q[
(
(`datebegin` >= 1950 AND `datebegin` <= 1959)
OR (`dateend` >= 1950 AND `dateend` <= 1959)
)
OR (`datebegin` <= 1950 AND `dateend` >= 1959)
])
Those "zero" dates are kind of annoying from a query perspective, they'd be better off as NULL so they wouldn't need to be excluded here. Since NULL is never greater than, less than, or equal to anything, it's invisible to these queries. Zero, on the other hand, is a valid number and has to be excluded.
As an example of how this works with ranges:
records = where(datebegin: (1950..1959)).or(dateend: (1950..1959))
Those are expressed with the BETWEEN operator. From an indexing perspective that's usually at least a little faster than a bounded range using AND.

Linq to Sql Concat Issue

So I have this function:
public static BaseList GetVersesByChapterVerseRanges(string translation, BaseList criteriaList)
{
BaseList returnValue = new BaseList();;
if(criteriaList.Count() > 0)
{
List<VerseMaster.BusinessLayer.Vers> queryList = new List<Vers>();
int bookId = criteriaList[0].Book.BookId;
int StartChapter = criteriaList[0].StartChapter;
int EndChapter = criteriaList[0].EndChapter;
int StartVerse = criteriaList[0].StartChapterStartVerse;
int EndVerse = criteriaList[0].EndChapterEndVerse;
var searchQuery = (from v in VerseMaster.BusinessLayer.Controller.Controller.VerseMasterEntities.Verses where v.Translation.ToLower().StartsWith(translation.ToLower()) && v.BookId == bookId && v.ChapterNumber >= StartChapter && v.ChapterNumber <= EndChapter && (v.ChapterNumber == StartChapter ? (v.VerseNumber >= StartVerse) : true) && (v.ChapterNumber == EndChapter ? (v.VerseNumber <= EndVerse) : true) orderby v.ChapterNumber, v.VerseNumber ascending select v);
for(int i = 1; i < criteriaList.Count(); i++)
{
bookId = criteriaList[i].Book.BookId;
StartChapter = criteriaList[i].StartChapter;
EndChapter = criteriaList[i].EndChapter;
StartVerse = criteriaList[i].StartChapterStartVerse;
EndVerse = criteriaList[i].EndChapterEndVerse;
VerseMaster.BusinessLayer.DataObjects.Helper.VerseSearchCriteria criteria = criteriaList[i];
searchQuery = (System.Linq.IOrderedQueryable<VerseMaster.BusinessLayer.Vers>)searchQuery.Concat(from v in VerseMaster.BusinessLayer.Controller.Controller.VerseMasterEntities.Verses where v.Translation.ToLower().StartsWith(translation.ToLower()) && v.BookId == bookId && v.ChapterNumber >= StartChapter && v.ChapterNumber <= EndChapter && (v.ChapterNumber == StartChapter ? (v.VerseNumber >= StartVerse) : true) && (v.ChapterNumber == EndChapter ? (v.VerseNumber <= EndVerse) : true) orderby v.ChapterNumber, v.VerseNumber ascending select v);
}
string traceString = ((System.Data.Objects.ObjectQuery)searchQuery).ToTraceString();
foreach (var entVerse in searchQuery)
{
VerseMaster.BusinessLayer.DataObjects.IVerse verse = new VerseMaster.BusinessLayer.DataObjects.Verse();
LoadVerseFromEntityVerse(ref verse, entVerse);
Console.Write(String.Format("Chapter={0} Verse={1} Text={2}\n", entVerse.ChapterNumber, entVerse.VerseNumber, entVerse.Verse));
//returnValue.Add((VerseMaster.BusinessLayer.DataObjects.Verse)verse);
}
}
return returnValue;
}
So for some reason I had to convert each of the parameters that go into the linq query into standard ints because of an error, not sure if its related. So the generated sql is:
SELECT
[UnionAll2].[C1] AS [C1],
[UnionAll2].[C2] AS [C2],
[UnionAll2].[C3] AS [C3],
[UnionAll2].[C4] AS [C4],
[UnionAll2].[C5] AS [C5],
[UnionAll2].[C6] AS [C6]
FROM (SELECT
[UnionAll1].[VerseId] AS [C1],
[UnionAll1].[ChapterNumber] AS [C2],
[UnionAll1].[VerseNumber] AS [C3],
[UnionAll1].[Verse] AS [C4],
[UnionAll1].[Translation] AS [C5],
[UnionAll1].[BookId] AS [C6]
FROM (SELECT
[Extent1].[VerseId] AS [VerseId],
[Extent1].[ChapterNumber] AS [ChapterNumber],
[Extent1].[VerseNumber] AS [VerseNumber],
[Extent1].[Verse] AS [Verse],
[Extent1].[Translation] AS [Translation],
[Extent1].[BookId] AS [BookId]
FROM [dbo].[Verses] AS [Extent1]
WHERE (( CAST(CHARINDEX(LOWER(#p__linq__0), LOWER([Extent1].[Translation])) AS int)) = 1) AND ([Extent1].[BookId] = #p__linq__1) AND ([Extent1].[ChapterNumber] >= #p__linq__2) AND ([Extent1].[ChapterNumber] <= #p__linq__3) AND ((CASE WHEN ([Extent1].[ChapterNumber] = #p__linq__4) THEN CASE WHEN ([Extent1].[VerseNumber] >= #p__linq__5) THEN cast(1 as bit) WHEN ( NOT ([Extent1].[VerseNumber] >= #p__linq__5)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1) AND ((CASE WHEN ([Extent1].[ChapterNumber] = #p__linq__6) THEN CASE WHEN ([Extent1].[VerseNumber] <= #p__linq__7) THEN cast(1 as bit) WHEN ( NOT ([Extent1].[VerseNumber] <= #p__linq__7)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1)
UNION ALL
SELECT
[Extent2].[VerseId] AS [VerseId],
[Extent2].[ChapterNumber] AS [ChapterNumber],
[Extent2].[VerseNumber] AS [VerseNumber],
[Extent2].[Verse] AS [Verse],
[Extent2].[Translation] AS [Translation],
[Extent2].[BookId] AS [BookId]
FROM [dbo].[Verses] AS [Extent2]
WHERE (( CAST(CHARINDEX(LOWER(#p__linq__8), LOWER([Extent2].[Translation])) AS int)) = 1) AND ([Extent2].[BookId] = #p__linq__9) AND ([Extent2].[ChapterNumber] >= #p__linq__10) AND ([Extent2].[ChapterNumber] <= #p__linq__11) AND ((CASE WHEN ([Extent2].[ChapterNumber] = #p__linq__12) THEN CASE WHEN ([Extent2].[VerseNumber] >= #p__linq__13) THEN cast(1 as bit) WHEN ( NOT ([Extent2].[VerseNumber] >= #p__linq__13)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1) AND ((CASE WHEN ([Extent2].[ChapterNumber] = #p__linq__14) THEN CASE WHEN ([Extent2].[VerseNumber] <= #p__linq__15) THEN cast(1 as bit) WHEN ( NOT ([Extent2].[VerseNumber] <= #p__linq__15)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1)) AS [UnionAll1]
UNION ALL
SELECT
[Extent3].[VerseId] AS [VerseId],
[Extent3].[ChapterNumber] AS [ChapterNumber],
[Extent3].[VerseNumber] AS [VerseNumber],
[Extent3].[Verse] AS [Verse],
[Extent3].[Translation] AS [Translation],
[Extent3].[BookId] AS [BookId]
FROM [dbo].[Verses] AS [Extent3]
WHERE (( CAST(CHARINDEX(LOWER(#p__linq__16), LOWER([Extent3].[Translation])) AS int)) = 1) AND ([Extent3].[BookId] = #p__linq__17) AND ([Extent3].[ChapterNumber] >= #p__linq__18) AND ([Extent3].[ChapterNumber] <= #p__linq__19) AND ((CASE WHEN ([Extent3].[ChapterNumber] = #p__linq__20) THEN CASE WHEN ([Extent3].[VerseNumber] >= #p__linq__21) THEN cast(1 as bit) WHEN ( NOT ([Extent3].[VerseNumber] >= #p__linq__21)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1) AND ((CASE WHEN ([Extent3].[ChapterNumber] = #p__linq__22) THEN CASE WHEN ([Extent3].[VerseNumber] <= #p__linq__23) THEN cast(1 as bit) WHEN ( NOT ([Extent3].[VerseNumber] <= #p__linq__23)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1)) AS [UnionAll2]
So the problem is that for some reason its treating each of the parameters I give it as if I sent 3 sets of the same parameter and concatenated so its returning the same set of verses 3 times. I'm not sure why its doing this as I am not an expert of linq or the entity framework, any suggestions?
This is a very tricky example of the modified closure issue. In the for loop you generate a query part that uses the variables bookId etc. At the time that your query is executed it uses the values that these variables have at that moment, which are the values after the last iteration of the loop. (The tricky part is that usually the loop variable is captured, but here it is about variables that were declared outside the loop scope).
It would be different if you declared the variables within the for loop, because each query part would capture its own instance of the variable (which is called a closure).
The good news: you can do this and at the same time clean up your code!
if(criteriaList.Count() > 0)
{
IQueryable<Verse> baseQuery = null;
for(int i = 0; i < criteriaList.Count(); i++) // starting i = 0 now !
{
int bookId = criteriaList[0].Book.BookId;
int StartChapter = criteriaList[0].StartChapter;
int EndChapter = criteriaList[0].EndChapter;
int StartVerse = criteriaList[0].StartChapterStartVerse;
int EndVerse = criteriaList[0].EndChapterEndVerse;
searchQuery = (IOrderedQueryable<Vers>)searchQuery.Concat(
from v in Controller.Controller.VerseMasterEntities.Verses
where v.Translation.ToLower().StartsWith(translation.ToLower())
&& v.BookId == bookId
&& v.ChapterNumber >= StartChapter
&& v.ChapterNumber <= EndChapter
&& (v.ChapterNumber == StartChapter ? (v.VerseNumber >= StartVerse) : true)
&& (v.ChapterNumber == EndChapter ? (v.VerseNumber <= EndVerse) : true)
select v);
if (i == 0)
baseQuery = searchQuery;
else
baseQuery = baseQuery.Concat(searchQuery);
}
...
(do the ordering later)

Elegant algorithm to detect overlapping periods with unbounded ends

My question is the same as Algorithm to detect overlapping periods.
But in my case, a period can be unbouded (No End Date, ie. NULL).
I can't find an elegant way do to that.
For unbounded end dates, you could also do something like:
a.end = a.end == NULL ? MAXDATE : a.end;
b.end = b.end == NULL ? MAXDATE : b.end;
bool overlap = a.start < b.end && b.start < a.end;
Or this could work:
bool overlap = (a.start < b.end || b.end == NULL) && (b.start < a.end || a.end == NULL);

Resources