Difference between revisions of "ITrack/Appraisal Extension"

From ISoft Wiki
Jump to navigationJump to search
(Auction And Remote Source Appraisal Capabilities)
Line 27: Line 27:
# Grab a session ID using `f_open_session`.
# Grab a session ID using `f_open_session`.
# Insert items into toappraise using your sessionid, a unique key for the inventoryid, and fill out as much of the rest as you can, placing NULL values where you don't have any info.
# Insert items into toappraise using your sessionid, a unique key for the inventoryid, and fill out as much of the rest as you can, placing NULL values where you don't have any info.
# Appraise your inserted data using `f_appraise_session` with your sessionid.
# Appraise your inserted data using `p_appraise_session` with your sessionid and origin code.
# Read back your appraised values from toappraise.value.
# Read back your appraised values from toappraise.value.
# From here you can add or remove items and appraise again using any origin as many times as you like.
# From here you can add or remove items and appraise again using any origin as many times as you like.
Line 53: Line 53:
#* Inventory Type ID (integer)
#* Inventory Type ID (integer)
#* Category (string)
#* Category (string)
#* Manufacturer (string)
#* Make (string)
#* Model (string)
#* Model (string)
#* Part Manufacturer (string)
#* Part Model (string)
#* Year (int)
# Add that item to the appraisal array by calling the following:
# Add that item to the appraisal array by calling the following:
#* APPRAISALMESSAGE.mapItems[itItem.GetID()] = ITAppraisalItem
#* APPRAISALMESSAGE.mapItems[itItem.GetID()] = ITAppraisalItem
Line 82: Line 85:
#* Inventory Type ID (integer)
#* Inventory Type ID (integer)
#* Category (string)
#* Category (string)
#* Manufacturer (string)
#* Make (string)
#* Model (string)
#* Model (string)
#* Part Manufacturer (string)
#* Part Model (string)
#* Year (int)
# Add that item to the appraisal array by calling the following:
# Add that item to the appraisal array by calling the following:
#* APPRAISALMESSAGE.mapItems[itItem.GetID()] = ITAppraisalItem
#* APPRAISALMESSAGE.mapItems[itItem.GetID()] = ITAppraisalItem
Line 106: Line 112:


=== Adding an Origin ===
=== Adding an Origin ===
Origins have become much more dynamic than their original enumerated values.  Unfortunately, due to MySQL's requirement that functions don't run dynamic queries, we have to remember to do some specific function/procedure changes when adding a new Origin.
Origins have become much more dynamic than their original enumerated values.


==== All Origins need you to do the following: ====
==== All Origins need you to do the following: ====
Line 113: Line 119:
** The code is what gets referenced in ITrack and database function code, and does not change after creation
** The code is what gets referenced in ITrack and database function code, and does not change after creation
** The function is the suffix of the function that builds the appraisal data from scratch
** The function is the suffix of the function that builds the appraisal data from scratch
* Create a new function `f_build_<function>`, where function is the value in origin.function.  This function will enter in data to the appraisal table, and must match the inputs (origin INT, nAuctionList TEXT)
* Create a new procedure `p_build_<function>`, where function is the value in origin.function.  This procedure will enter in data to the appraisal table, and must match the inputs (origin INT, nAuctionList TEXT)
* Add a case block to `p_build_appraisal` for your new origin
** This step becomes unnecessary when a function can call a procedure that has dynamic code in MySQL >.<


==== If your Origin has a way to cache results (such as a static auction list or special number): ====
==== If your Origin has a way to cache results (such as a static auction list or special number): ====
Line 121: Line 125:


==== If your Origin uses a list of auctions: ====
==== If your Origin uses a list of auctions: ====
* A call to `p_build_appraisal_base` will do all the appraisal data generation for you, so just put that in `f_build_<function>`
* A call to `p_build_appraisal_base` will do all the appraisal data generation for you, so just put that in `p_build_<function>`


==== If your Origin has a cache check value AND you want the cache to be generated automatically: ====
==== If your Origin has a cache check value AND you want the cache to be generated automatically: ====
* Add a call to `f_build_appraisal` in `f_generate_full_cache` for your Origin.
* Add a call to `p_build_appraisal_real` in `p_generate_full_cache` for your Origin.


[[Category:ITrack/Code]]
[[Category:ITrack/Code]]

Revision as of 17:39, 26 July 2010

The Appraisal Extension is used to allow our products to give per-item appraisals by evaluating the item's performance to Berryhill Auctioneers' previous auctions.

General

In general, the Appraisal Extension requires the following:

  • ITrack. It can be Pro, AX, Enterprise, or anything that uses ITrack.exe
    • OR any specially-build applications designed by ISoft.
  • The AppraisalExtension.dll file.
  • Connection configuration data. This is usually located in the host.ini file provided with ITrack.
  • Company permission. This is controlled by ISoft, and those interested in being added should contact our Sales department.

All of these can be arranged by contacting ISoft.

Usage

Once the Appraisal Extension is installed and configured, most appraisals will be done with a list of parts (or, less commonly, a single part) and a button press. ITrack users should look to their Search screens. When the button is pressed, the screen will look up the appraisal data, which may take a few moments, and then report it on your screen.

Methodology

Appraisals are done using Berryhill Auctioneers' auction results. These allow us to get and keep current frames of reference for car and truck parts. ISoft keeps a special database that is maintained by function calls and software interaction so that administrating this data is mostly an automatic process.

Making Appraisal Data

Whenever a Berryhill Auction is closed, the results from the auction are incorporated into a cache using the database function `f_generate_full_cache`. This is a safe function call, and if no work needs to be done, it won't do anything. Doing this will not interrupt appraisals in progress, but it can end up having different results sent back. We usually update the cache at night for this reason.

Not all origins are generated by `f_generate_full_cache`. Some origins, such as ORIGIN_CUSTOM and ORIGIN_HTP_LIVE are on their own schedules (custom is generated when it gets called, and htp_live is generated on a weekly basis).

Using Appraisal Data

In order to appraise an item or set of items, the following function calls should be used. Order is important!

  1. Grab a session ID using `f_open_session`.
  2. Insert items into toappraise using your sessionid, a unique key for the inventoryid, and fill out as much of the rest as you can, placing NULL values where you don't have any info.
  3. Appraise your inserted data using `p_appraise_session` with your sessionid and origin code.
  4. Read back your appraised values from toappraise.value.
  5. From here you can add or remove items and appraise again using any origin as many times as you like.
  6. Close your session using `f_close_session` with your sessionid.

Don't worry about cleaning your results, as closing your session does it automatically. If you accidentally disconnect or lose your sessionid without cleaning up, don't fret! Rows are cleaned up on a timing basis, as well.

Code

You can use the Appraisal Extension interface, or make database calls directly.

Appraisal Extension - External Calls

The easiest way to get appraisals is to use the following sequence of remote calls:

  1. Check to see that the appraisal extension is valid by calling something like
    • ITAppraisal::GetInstance()->IsEnabled()
  2. Create an APPRAISALMESSAGE object and set APPRAISALMESSAGE.itData.itOrigin to an appropriate origin. (Use APPRAISALMESSAGESINGLEITEM if you only have a single item)
  3. Optional - Ask the user for the appraisal type
    1. Set APPRAISALMESSAGE.itData.nAuctionID to the current auction you're appraising at (leave it alone if you don't know what this should be)
    2. Call the following to run the dialog:
      • CallExternalFunction(<master window handle>, "Appraisal", "AppraisalOriginDialog", <extension name>, &APPRAISALMESSAGE.itData, NULL)
    3. The user will use the dialog that pops up, and control of the program will be returned.
  4. Create an ITAppraisalItem object.
  5. For each item in the array, set the following values in your ITAppraisalItem (skip if you don't have them)
    • Unique Identifier (integer) (partnum / inventoryid is a good choice)
    • Inventory Type ID (integer)
    • Category (string)
    • Make (string)
    • Model (string)
    • Part Manufacturer (string)
    • Part Model (string)
    • Year (int)
  6. Add that item to the appraisal array by calling the following:
    • APPRAISALMESSAGE.mapItems[itItem.GetID()] = ITAppraisalItem
  7. When you've added all the items to appraise, call:
    • Multiple items: CallExternalFunction(<master window handle>, "Appraisal", "AppraiseItems", <extension name>, &APPRAISALMESSAGE, NULL);
    • Single item: CallExternalFunction(<master window handle>, "Appraisal", "AppraiseItem", <extension name>, &APPRAISALMESSAGESINGLEITEM , NULL);
  8. When control is returned, you can retrieve your appraisal values by calling:
    • APPRAISALMESSAGE.mapItems[<unique id>].GetAppraisedValue()
    • OR MapFind(itMessage.mapItems, <unique id>, itItem); itItem.GetAppraisedValue();

Appraisal Extension - Direct Object Calls

In some cases, you'll want to appraise the same data set more than twice, and in this case you can avoid the setup overhead of the objects by calling the appraisal object directly:

  1. Check to see that the appraisal extension is valid by calling something like
    • ITAppraisal::GetInstance()->IsEnabled()
  2. Get an instance of the appraisal object:
    • ITAppraisal *pitAppraisal = ITAppraisal::GetInstance();
  3. Create an empty CString for your session ID.
  4. Create an APPRAISALDATA object and set APPRAISALMESSAGE.itData.itOrigin to an appropriate origin.
    • If it's your first call, you *must* call ITAppraisalExtension::Initialize(m_pwndMaster) OR set itData.pMasterWnd to Master's window handle.
  5. Optional - Ask the user for the appraisal type
    1. Call pitAppraisal->DoAppraisalOriginDialog(APPRAISALMESSAGE.itData);
    2. The user will use the dialog that pops up, and control of the program will be returned.
  6. Create an ITAppraisalItem object.
  7. For each item in the array, set the following values in your ITAppraisalItem (skip if you don't have them)
    • Unique Identifier (integer) (partnum / inventoryid is a good choice)
    • Inventory Type ID (integer)
    • Category (string)
    • Make (string)
    • Model (string)
    • Part Manufacturer (string)
    • Part Model (string)
    • Year (int)
  8. Add that item to the appraisal array by calling the following:
    • APPRAISALMESSAGE.mapItems[itItem.GetID()] = ITAppraisalItem
  9. When you've added all the items to appraise, call:
    1. pitAppraisal->OpenSession(sessionID) to get your session id
    2. pitAppraisal->AddItemsToSession(sessionID, APPRAISALMESSAGE.mapItems) to add your items
    3. pitAppraisal->AppraiseSession(sessionID, APPRAISALMESSAGE.itData)
    4. pitAppraisal->GetAppraisedValues(sessionID, APPRAISALMESSAGE.mapItems) to fill out your values
    5. If you wish, alter APPRAISALMESSAGE.itData and go back to step 3 to do a different appraisal
    6. pitAppraisal->CloseSession(sessionID) to clean up your appraisal session.
  10. Let your APPRAISALMESSAGE object go out of scope or deallocate it.

Caveats

You can use the APPRAISALMESSAGE multiple times, and when you're done with it, just let it go out of scope or deallocate it. You never need to worry about cleaning up the ITAppraisal object either.

Don't mess around with the memory location of pitAppraisal. It's a singleton, and anything you do to it will be reflected any place its code is called.

ITAppraisal is *not* thread-safe at the moment.

Database

The following are nifty rules for altering the way that appraisals are done.

Adding an Origin

Origins have become much more dynamic than their original enumerated values.

All Origins need you to do the following:

  • Add an entry into `origin`
    • The name is what users see
    • The code is what gets referenced in ITrack and database function code, and does not change after creation
    • The function is the suffix of the function that builds the appraisal data from scratch
  • Create a new procedure `p_build_<function>`, where function is the value in origin.function. This procedure will enter in data to the appraisal table, and must match the inputs (origin INT, nAuctionList TEXT)

If your Origin has a way to cache results (such as a static auction list or special number):

  • Add an entry to `f_get_auction_list` that returns the cache check value for your Origin (this can be a list of auctions, or a date, or hash, or whatever)

If your Origin uses a list of auctions:

  • A call to `p_build_appraisal_base` will do all the appraisal data generation for you, so just put that in `p_build_<function>`

If your Origin has a cache check value AND you want the cache to be generated automatically:

  • Add a call to `p_build_appraisal_real` in `p_generate_full_cache` for your Origin.