$record_values = new Criteria();
$record_values->add(TblfieldsPeer::CUSTOMER_ID, $company_qu_id);
$record_values->add(TblfieldsPeer::RECORD_TYPE_ID, $query_rtype);
for($fieldid_arrayCount=0;$fieldid_arrayCount<count($fieldIds);$fieldid_arrayCount++)
{
$currentFieldId = $fieldIds[$fieldid_arrayCount];
if(isset($query_values[$fieldid_arrayCount]))
{
$criterion1 = $record_values->getNewCriterion(TblfieldsPeer::FIELDS_ID, $currentFieldId);
$criterion1->addAnd($record_values->getNewCriterion(TblfieldsPeer::FIELD_VALUES, $query_values[$fieldid_arrayCount]));
$record_values->add($criterion1);
}
}
$record_values_results = TblfieldsPeer::doSelect($record_values, $con1);
But only last criterion is added. I check the databases in debug toolbar only the last criterion is there. What could be the problem.
Please help me....
I'm not a propel expert but maybe you could try to use 2 alternative changes:
to use addAnd statement instead of add one in $record_values->add($criterion1)
to put $record_values->add($criterion1) outside the (of course after) cycle changing $criterion1 in a field outer the cycle and using only the addAnd statement for $criterion1
Related
After clicking the "Return" action on a selected item from a completed Purchase Receipt, we're trying to get the "Open PO Line" value to default to false. Anyone know how customize this?
The field defaulting seems to be overwritten when we press the "Return" button. We've tried several different events in the grid but none of the seem to work.
The desired result is to default the "Open PO Line" to false after a return and once the return is released the Purchase Order line associated with the return should remain completed.
Research
The AllowOpen field on POReceiptLine is a PXBool. This means that the value must be populated via a PXDBScalar, PXFormula, etc. or via some business logic in the graph. To see what is happening, let's look at the DAC for POReceiptLine...
#region AllowOpen
public abstract class allowOpen : PX.Data.BQL.BqlBool.Field<allowOpen> { }
protected Boolean? _AllowOpen;
[PXBool()]
[PXUIField(DisplayName = "Open PO Line", Visibility = PXUIVisibility.Service, Visible = true)]
public virtual Boolean? AllowOpen
{
get
{
return this._AllowOpen;
}
set
{
this._AllowOpen = value;
}
}
#endregion
As you can see, there isn't any logic to this field in the DAC, so we need to turn to the graph to see how it is used. (Even if there were logic in the DAC, we would need to see if the graph does something. However, logic in the DAC might have been an easy override with CacheAttached - unfortunately, not in this case.)
Let's turn to POReceiptEntry where the return is handled. We find AllowComplete and AllowOpen being set in the POReceiptLine_RowSelected event, as we would expect since it must be populated on the graph side of code having no logic in the DAC.
if ((row.AllowComplete == null || row.AllowOpen == null) && fromPO)
{
POLineR source = PXSelect<POLineR,
Where<POLineR.orderType, Equal<Required<POLineR.orderType>>,
And<POLineR.orderNbr, Equal<Required<POLineR.orderNbr>>,
And<POLineR.lineNbr, Equal<Required<POLineR.lineNbr>>>>>>
.Select(this, row.POType, row.PONbr, row.POLineNbr);
// Acuminator disable once PX1047 RowChangesInEventHandlersForbiddenForArgs [Legacy, moved the exception here from PX.Objects.acuminator because the condition was changed]
row.AllowComplete = row.AllowOpen = (row.Released == true) ?
(row.ReceiptType != POReceiptType.POReturn ? source?.Completed == true : source?.Completed != true) :
(source?.AllowComplete ?? false);
The field is populated in the row.AllowComplete = row.AllowOpen = (row.Released == true) ?... section of code.
Subsequently, we see that the CopyFromOrigReceiptLine method sets this value to false on the "destLine" being created.
destLine.AllowOpen = false;
As that isn't "true" then we know this isn't our spot. Continuing on, we see in UpdatePOLineCompletedFlag that AllowComplete and AllowOpen are being set. This could be our spot (or one of them).
row.AllowComplete = row.AllowOpen = poLineCurrent.AllowComplete;
Side note: It is worth noting that this line appears twice in an if then else. In both cases it is going to be executed, therefore it would be better coding practice to place this identical statement AFTER the if then else since both the if and else conditions will execute this same statement regardless of the if.
This particular use appears to be pulling the value from the AllowComplete field of the PO Line being received. At this point, you should consider if you need to look upstream at the PO Line to see if the field there needs to be manipulated as well. I cannot answer that for you as your business case will drive the decision.
There also is a line in the Copy method that sets AllowComplete and AllowOpen.
aDest.AllowComplete = aDest.AllowOpen = (aSrc.CompletePOLine == CompletePOLineTypes.Quantity);
The Copy method is overloaded, and the other signature of the method sets the values to true.
aDest.AllowComplete = true;
aDest.AllowOpen = true;
Both of these cases may need customization as well, but I don't think it's the primary issue.
Next Steps
At this point, we see that either the field is being set in UpdatePOLineCompletedFlag or in methods that seem related to copying records. You will need to investigate further if the copy related methods warrant a change as well. However, I think the initial focus should be on the UpdatePOLineCompletedFlag method.
If we find the other points identified require customization, we likely will handle them all the same way... Override the base method/event, invoke the original method/event in our override, and then force the values to fit our business case. Careful testing will be needed since forcibly altering these values may create unforeseen negative ripples.
Something to try
We want to update (or create) a graph extension for POReceiptEntry to override the UpdatePOLineCompleteFlag method. This compiles, but it is completely untested on my part. We need to create a delegate and specify the PXOverride attribute. Then we want to execute the base method before we override the field(s) in question.
Note the extra code (commented out) as a reminder that you need to be careful of methods (typically events) updating our record in the cache and needing to be located so that we don't use a stale copy of the record. I don't think that's necessary in this case, but it seems to be somewhat obscure in code samples that I see. Of course, that is because I'm always looking at the code repository which rarely has graph extensions overriding event handlers!
#region CreateReceiptEntry Override
public delegate void UpdatePOLineCompleteFlagDelegate(POReceiptLine row, bool isDeleted, POLine aOriginLine);
[PXOverride]
public virtual void UpdatePOLineCompleteFlag(POReceiptLine row, bool isDeleted, POLine aOriginLine, UpdatePOLineCompleteFlagDelegate baseMethod)
{
//Execute original logic
baseMethod(row, isDeleted, aOriginLine);
/* If the base method has updated the cache, then we would need to locate the updated record in the cache to proceed
* This tends to be the case more often with event handlers, so it probably isn't needed in this case.
* This is just for reference as a training reminder
//If row has been updatd in the baseMethod, let's go get the updated cache values
POReceiptLine locateRow = Base.transactions.Locate(row);
if (locateRow != null) row = locateRow;
*/
//Override the fields to false - need to test to see if this creates any issues with breaking existing business logic
row.AllowComplete = row.AllowOpen = false;
}
#endregion
If this doesn't get you the specific answer you need, I hope it at least gives you some insight into how to hunt down "the spot" to change. I suspect you may need to update the POLine for a complete solution as hinted above. (See the event handler POReceiptLine_AllowOpen_FieldUpdated for the code that leads me to that conclusion.)
Good luck with your customization, and happy coding!
I have a Lua function where I build a table of value and attempt to add it to a global table with a named key.
The key name is pulled from the function arguments. Basically, it's a filename, and I'm pairing it up with data about the file.
Unfortunately, the global table always comes back nil. Here's my code: (let me know if you need to see more)
(Commented parts are other attempts, although many attempts have been deleted already)
Animator = Class{}
function Animator:init(atlasfile, stringatlasfriendlyname, totalanimationstates, numberofframesperstate, booleanstatictilesize)
-- Define the Animator's operation mode. Either static tile size or variable.
if booleanstatictilesize ~= false then
self.isTileSizeStatic = true
else
self.isTileSizeStatic = false
end
-- Define the total animation states (walking left, walking right, up down, etc.)
-- And then the total frames per state.
self.numAnimationStates = totalanimationstates or 1
self.numAnimationFrames = numberofframesperstate or 2
-- Assign the actual atlas file and give it a programmer-friendly name.
self.atlasname = stringatlasfriendlyname or removeFileExtension(atlasfile, 'animation')
generateAnimationQuads(atlasfile, self.atlasname, self.numAnimationStates, self.numAnimationFrames)
end
function generateAnimationQuads(atlasfile, atlasfriendlyname, states, frames)
spriteWidthDivider = atlasfile:getWidth() / frames
spriteHeightDivider = atlasfile:getHeight() / states
animationQuadArray = generateQuads(atlasfile, spriteWidthDivider, spriteHeightDivider)
animationSetValues = {atlasarray = animationQuadArray, width = spriteWidthDivider, height = spriteHeightDivider}
--gAnimationSets[#gAnimationSets+1] = atlasfriendlyname
gAnimationSets[atlasfriendlyname] = animationSetValues
--table.insert(gAnimationSets, atlasfriendlyname)
end
Note: when using print(atlasfriendlyname) and print(animationSetValues), neither are empty or nil. They both contain values.
For some reason, the line(s) that assign the key pair to gAnimationSets does not work.
gAnimationSets is defined a single time at the top of the program in main.lua, using
gAnimationSets = {}
Animator class is called during the init() function of a character class called Bug. And the Bug class is initialized in the init() function of StartState, which extends from BaseState, which simply defines dummy init(), enter(), update() etc. functions.
StartState is invoked in main.lua using the StateMachine class, where it is passed into StateMachine as a value of a global table declared in main.lua.
gAnimationSets is declared after the table of states and before invoking the state.
This is using the Love2D engine.
Sorry that I came here for help, I've been picking away at this for hours.
Edit: more testing.
Trying to print the animationQuadArray at the index gTextures['buganimation'] always returns nil. Huh?
Here's gTextures in Main.lua
gTextures = {
['background'] = love.graphics.newImage('graphics/background.png'),
['main'] = love.graphics.newImage('graphics/breakout.png'),
['arrows'] = love.graphics.newImage('graphics/arrows.png'),
['hearts'] = love.graphics.newImage('graphics/hearts.png'),
['particle'] = love.graphics.newImage('graphics/particle.png'),
['buganimation'] = love.graphics.newImage('graphics/buganimation.png')
}
Attempting to return gTextures['buganimation'] returns a file value as normal. It's not empty.
My brain is so fried right now I can't even remember why I came to edit this. I can't remember.
Global table in Main.lua, all other functions can't access it.
print(gTextures['buganimation']) works inside the function in question. So gTextures is absolutely accessible.
Table isn't empty. AnimationSetValues is not empty.
I'm adding second answer because both are correct in context.
I ended up switching IDE's to VS Code and now the original one works.
I was originally using Eclipse LDT with a Love2D interpreter and in that environment, my original answer is correct, but in VS Code, the original is also correct.
So Dimitry was right, they are equivalent, but something about my actual Eclipse setup was not allowing that syntax to work.
I switched to VS Code after I had another strange syntax problem with the interpreter where goto syntax was not recognized and gave a persistent error. The interpreter thought goto was the name of a variable.
So I switched, and now both things are fixed. I guess I just won't use LDT for now.
Solution: Lua syntax. Brain Fry Syndrome
I wrote:
animationSetValues = {atlasarray = animationQuadArray, width = spriteWidthDivider, height = spriteHeightDivider}
Should be:
animationSetValues = {['atlasfile']=atlasfile, ['atlasarray']=animationQuadArray, ['width']=spriteWidthDivider, ['height']=spriteHeightDivider}
Edit: I'm fully aware of how to use answers. This was posted here to reserve my spot for an answer so I could edit it later when I returned back home, which is exactly what I'm doing right now. I'll keep the old post for archival purposes.
Original:
I solved it. I apologize for not posting the solution right now. My brain is melted into gravy.
I will post it tomorrow. Just wanted to "answer" saying no need to help. Solved it.
Solution is basically, "oh it's just one of those Lua things". Wonderful. I'm having so much fun with this language - you can tell by my blank expression.
From the language without line endings or brackets, but forced print parentheses... ugh. I'm going back to C# when this class is done.
I occure a problem which I do not understand. Following code does not work:
AccountingEntity accountingEntity = AccountingEntity.get(params.id);
accountingEntity.setLifecycleStatusToArchived();
accountingEntity.save(flush:true);
Where the method setLivecylceStatusToArchived looks like:
void setLifecycleStatusToArchived() {
this.lifecycleStatus = AccountingEntity.LIFECYCLE_ARCHIVED; //predefined static variable
this.considerForRankingJob = false;
this.dateArchived = new Date();
}
Problem is, that the entity is not updated.
No validation erros when I use accountingEntity.validate() in advance.
However, this code works:
AccountingEntity accountingEntity = AccountingEntity.get(params.id);
accountingEntity.setDateArchived(new Date());
accountingEntity.setConsiderForRankingJob(false);
accountingEntity.setLifecycleStatus(AccountingEntity.LIFECYCLE_ARCHIVED);
accountingEntity.save(flush:true);
The code did not work any more after update from Grails 3.2.9 to 3.3.0.RC1 (Gorm 6.1.5) unless I followed all the steps in the guide (http://docs.grails.org/3.3.x/guide/upgrading.html) and the rest of the code is working properly (also database accesses etc.)
Has anybody an idea? What the problem could be?
Thanks in advance and best regards!
The short answer is dirty checking. When you are setting properties inside the instance method Grails doesn't know they are dirty.
See the following github issue for how to resolve the problem:
https://github.com/grails/grails-data-mapping/issues/961
you have 2 options:
call markDirty every time you change an internal field. This will be
better for performance or as per
http://gorm.grails.org/latest/hibernate/manual/index.html#upgradeNotes
use
hibernateDirtyChecking: true
How can I determine, at runtime, if a list in Dart is a "fixed list" ?
There are (at least) three ways to create a fixed-length list in Dart:
var fixed = new List(5); // fixed at five elements
var alsoFixed = new List.filled(5, null); // fixed at five elements, set to null
var fixedToo = new List.from([1,2,3], growable: false);
How do I ask, in code, if fixed, alsoFixed, and fixedToo are fixed-length?
You can try to add an element and remove it to know if the list has a fixed length:
bool hasFixLength(List list) {
try {
list
..add(null)
..removeLast();
return false;
} on UnsupportedError {
return true;
}
}
runtimeType can be used for that, but shouldn't because it's not very reliable especially with dart2js otherwise there isn't. AFAIR there were several requests to add support for this but was declined.
We did not add any way to see if a list is fixed (or const).
So far, we have only encountered one use case where this would fit into well-written code: checking that a function returned a mutable array. We decided that this use case was not worth changing the API.
Most of the time, an additional boolean flag that asks to modify an existing list is cleaner (since then, the caller can decide what the callee should do).
If you have another use case, please let us know and we will investigate.
I'm editing an ActionScript file and I've run into an issue.
When I put the following, everything is fine.
if (x=x) {
//blah
}
If I put this, it says unexpected ; for one line and } for the another:
for (x=x) {
//blah
}
Same with when I put this:
while (x=x) {
//blah
}
Of course I only put those there as examples to test it, because I thought something was wrong with my code. Is ActionScript, in this part of my file, only allowing IF statements or what? I need to do the same long series of steps to two different strings, but I don't want to put the code in there twice. Do I have to make a function?
Read up on the looping syntax here.
The For loop doesn't take a boolean (true/false), it needs a counter, a boolean check for the limit and an increment.
i.e.
for (counter; condition; action){
statements;
}
I've never used action script but I would suggest trying this with
x==x
Since once = is assignment, not a comparison.
if the for loop still does not function try
for(;x==x;){
}
the semicolons tell it that you want to only use the second statement in the for loop declaration, the condition; since for loops use three statements,
for (variable; condition; iterative action)
by placing semicolons before and after x==x you specify only the condition, which seems to be what you're trying to do.
Turns out using any IF or WHILE statements caused the error no matter what was inside.
I was able to accomplish what I wanted by making another function and sending each string though those.
Appreciate the help, voted up on both of y'all.
you have to write it like this:
if(a==x){
// do that
}
for (x=0; x<maxloops; x++){
// do that
}
while(a==x){
}
The = symbol is used to define values to varialbes, while == has to be used when you comparing / checking (i.e. whether this is equal to that). This both applies to IF and WHILE
the FOR LOOP. Let's say that you want to execute the action "do that" 10 times. then you write
for (x=0; x<10; x++){
// do that
}
the first part x=0 is the definition of the counting variable and its initial value
the second part is the condition (run the loop as long as x is less than 10)
the third part is the stepper. (how the counter will raise its value in each loop). x++ is a short way to write x = x +1;