Class with fixed property values

Can a Class with fixed property values have property values defined by a variable.
for example: (dictionary from a credit card authorizing program)

Class Sale: A sale transaction
Properties:

Type Preauthorize/Normal/Refund/Force

I try to define the “type” of sale from a variable, but it will not let me.

Set x to “Preauthorize”
Set the type of sale to x

The script errors on the x variable.

the error message is: NSUnknownKeyScriptError

Does this make sense to anybody?

In other words, can I make a variable to define an application keyword that a property uses?

Yes, and no, using properties to identify the types.

You see, even in ‘the real world’, type names are simply identifiers themselves, usually to an index of values, so you can get a similar result by using properties for the values:

property Preauthorize : 1
property Normal : 2
property Refund : 3
property Force : 4

set sale to {type:missing value} -- start off with an empty record

set x to Preauthorize
set the type of sale to x

if type of sale is Preauthorize then
	display dialog "We got a pre-auth!"
end if

This is interesting, but I cannot get it to work.’

It seems that the variable x is not referenced to the index of values above, it is just being defined as “preauthorize”.

How do you get the variable to reference one of the index values?

this is what I’m trying to do;

tell application “filemaker pro”
Set x to … – set a variable to a value for the type of sale from filemaker
end tell

tell application “credit card”–application to process creditcards

make new sale
set type of sale to x–where type of sale is a constant of the application
end tell

Is there a way to assign or coerce the variable into the constant. Make x the type of sale?
from what I have been reading, one cannot do this. But I think you guys know more than them.

This doesn’t make any sense.

Assuming ‘sale’ is a class of object, you need to do something more along the lines of:


set newSale to make new sale
set type of newSale to x

Does that work any better?

Sale is an object class

“type” is a property of that object class along with “amount”, “card number”, “expiration date” etc.

amount is an integer
card number is unicode text

but the property “type” has only 4 constants (preauthorize, normal. etc) as mentioned above. The roadblock is trying to assign the “type” of sale via a variable. I don’t think this can be done?

Sorry if this is confusing, but it’s confusing to me. Still learning applescript, but have made great progress thanks to you guys.

I’d assumed that, and that being the case the code:

make new sale
set type of sale to x

makes no sense.

If you want to make a new object of type sale to need to assign a variable name to it:

set newSale to make new sale

you can then reference the newly-created sale object via its name newSale

set type of newSale to x

You cannot set the type of sale since that is the main object class.

Ok, I see what you are getting at. The miscommunication is my fault, I was leaving out a script line to make things shorter

Here is an example of a part of a working script:

tell application "AuthPayX Client"
	make new sale
	set the type of sale 1 to normal--can only be one of 4 values-normal-refund..ect
	set the account number of sale 1 to accountnumber
  tell sale 1
		submit transaction
	end tell
end tell

What I want to do is to assign the “type” of sale from a variable

Example:

tell application "FileMaker Pro"
	set saletype to cell "saletype" in current record in document "DISH USA INVOICES"
	set accountnumber to cell "Account" in current record in document "DISH USA INVOICES"
end tell

tell application "AuthPayX Client"
	make new sale
	set the type of sale 1 to saletype
	set the account number of sale 1 to accountnumber
 	tell sale 1
		submit transaction
	end tell

It will not allow this because the variable “saletype” must be a constant. What I want to do is define saletype from Filemaker. Is this now making more sense?

Thank you for your responses.

OK, I understand a little better now.

The trouble is that Filemaker will only return a string object as the result of the get cell line. Although, to us, the string returned from Filemaker matches the options for ‘type’ as far as AuthPay is concerned, AppleScript sees them as totally different.

The easiest way to deal with this is to simply:

tell application "FileMaker Pro" 
   set saletype to cell "saletype" in current record in document "DISH USA INVOICES" 
   set accountnumber to cell "Account" in current record in document "DISH USA INVOICES" 
end tell 

then:

tell application "AuthPayX Client" 
   make new sale 
if saletype = "Normal" then
	set the type of sale 1 to Normal
else if saletype = "Preauthorize" then
	set the type of sale 1 to Preauthorize
else if saletype = "Refund" then
	set the type of sale 1 to Refund
else if saletype = "Force" then
	set the type of sale 1 to Force
end if

In this way you’re kind of translating between strings and values understood by the application.

There’s one other thing I would change, too, which is the way you’re referencing the sale in AuthPayX.
In your code you are setting “type of sale 1 to x” which is OK but dangerous. While it might work all of the time in testing, it is ambiguous and may fail in the real world.
For example, what would happen if two sales came in very close to each other?
The first sale is for a $100 preauth and while this is processing another sale comes in as a normal $20 sale.
Since you’re using ‘sale 1’ the commands that are directed to the latter sale (normal $20) would be applied to the first one ($100 preauth), which is not what you want.

Instead, you should use a reference to the specific sale you’re processing:

 tell application "AuthPayX Client" 
set thisSale to make new sale

At this point, thisSale is a reference to a specific sale object as far as AuthPay X is concerned. If you looked at it from AppleScript’s perspective, it’s probably something like "sale ID 12345 of application “AuthPayX Client” - absolutely unambiguous and when it comes to setting the sale type:

set type of thisSale to Normal

this (internally) translates to ‘set type of sale ID 12345 of application “AuthPayX Client” to Normal’ which, again, is unambiguous and unaffected by any other actions going on at the time. Each run of the script would have ‘thisSale’ referencing a different sale object within AuthPayX Client and you’ll never run into an overlap.

This may not be a big deal for you right now, but it may be if you start processing lots of sales, and may definitely be in other applications, so it’s a good habit to get into.

Great, thank you a ton.

So far, the way of solving the latter problem you described, is to insert a line
“delete sale 1”

after the result of the sale is processed.

This is how I have handled it so far.

Thanks again!

That’s a really dangerous habit to get into.

While it may be OK in this particular case, it will lead to what’s called a ‘race condition’ under load. Race conditions are software bugs that occur when one part of a program modifies something that another part of the program is still using.

In this case I don’t know where this script is being called, but let’s assume, for the moment, it’s being used as part of a credit-card authorizaton system on a web site (but the same thing could be true in a store or other retail environment)

Customer 1 comes in and orders something, your script creates a ‘sale’ object in AuthPay and processes “sale 1” for authorization.

Now, one second after customer 1 places an order, customer 2 submits the order form for a different product. So the script is called again to create another ‘sale’ object in AuthPay, and then your script continues to modify “sale 1” Do you see the problem? ‘sale 1’ is the pending, incomplete sale for customer 1.

It gets worse if for some reason customer 2’s authorization completes before customer 1’s order does (maybe customer 1’s credit card has a problem and takes longer to authorize). In this case, the script for customer 2’s order, by your statement, deletes “sale 1”! Oops! it just deleted the other customer’s order!
And when customer 1’s order finally finishes the authorization process, you delete customer 2’s order (since that became “sale 1” when the previous sale was deleted).

Now you’re screwed.

A very simple change to your script to name the sale objects and then reference them by name rather than by relative index would eliminate the entire problem.

Race conditions can be very dangerous bugs. They often don’t show themselves and can lay dormant for years, and cause you untold grief when all of a sudden this program that you’ve used for years and come to rely on starts screwing up for no apparent reason.

While I obviously can’t force you to change your script, I strongly urge you to do so. Your future sanity might depend on it. :slight_smile:

VERY good point! I will work this into my revisions.

Thank you again.