PC & Web Xperience, Inc.
01/11/2001
Author: Jason A. Pattie
LastRevised: 2002/05/14
New features:
choosing of the equity account needs to be moved above the import of Buy investment transactions
QIF Import (Securities Information) Design
Read line by line and only keep a short term memory of the state in the file the parsing is currently located
When encountering "!Type:Security", read the:
N - name
S - ignore symbol
T - type of security (Bond, CD, Mutual Fund, Stock)
G - ignore goal type
^ - end of entry
Process the security entry by looking up all security sub-accounts (type 70 = stock) in the database and presenting the user with a list of securities to map the current QIF security to the database with if the QIF security does not match a security already in the database
When encountering "!Type:Invst", read each transaction at a time, encountering a transaction for every '^': (for each monetary or numeric value, remove all commas before processing -- i.e., quantity of shares, price, commission, etc.)
D - date (need to convert all dates (m[m]/[d_][d]/[yy] or m[m]/[d_][d]'_d) to the correct format MM/DD/YYYY)
N - action (Buy, BuyX, Sell, SellX, XIn, XOut, Div, ShrsIn, ShrsOut, StkSplit)
Y - security
I - price
Q - number of shares, split ratio
C - ignore cleared status
P - ignore
M - ignore
O - commission
L - transfer/class of the transaction
T - amount of transaction
U - ignore (valid?)
$ - amount transferred
^ - end of entry
When encountering "!Type:Prices", ignore lines up till next '^' (for now; eventually, prices will need to be imported into the database -- stock_price_tb)
Insert an "<unknown_account>" entry in the qif_account_tb in order to have it available for associating transactions that do not have an account entry in the QIF file
QIF Import Database Tables:
qif_class_tb
name
description
used
map_sub_entity (always sub-entity)
qif_category_tb
name
description
used
tax_related_item
tax_ref_num
income_expense_flag (true = income, false = expense)
map_account
map_sub_account
qif_account_tb
name
type (Bank, Cash, CCard, Invst - Port, Mutual, 401(k), Oth A, Oth L, Invoice, Tax, Bill)
sales_tax
description
used
credit_card_limit
balance
map_account
qif_security_tb
name
used
symbol
type (Bond, CD, Mutual Fund, Stock)
goal (College Fund, High Risk, Income, Low Risk)
map_sub_account
qif_prices_tb
price_symbol
price_amount
price_date
(not going to implement yet)
qif_memorized_list_tb
type (only care about KI meaning investment, all others are normal)
split_new_shares
split_old_shares
non-investment fields
trans_date
amount
cleared
check_number
payee
memo
investment fields
(not going to implement yet)
qif_account_list_tb (normal transactions)
qif_investment_list_tb (investment transactions)
trans_date
action
security
price
quantity
cleared
description
memo
commission
category
category_class
transfer_account
transfer_class
amount
transfer_amount
account (use <unknown_account> if this is coming from a QIF file that did not export an accounts list)
Investment actions
Implemented |
|
QIF code |
Our Action |
Needed items |
yes |
* |
Buy |
buy |
|
yes |
* |
Sell |
sell |
|
--- |
|
ReinvDiv |
cash dividend, buy |
dividend income account |
--- |
|
ReinvInt |
interest, buy |
interest revenue account |
--- |
|
ReinvLg |
cash transfer, buy |
ask user where money came from (account); if from same account, do not enter transfer |
--- |
|
ReinvMd |
cash transfer, buy |
|
--- |
|
ReinvSh |
cash transfer, buy |
|
yes |
* |
Reminder |
memo |
|
yes |
* |
RtrnCap |
return of capital |
|
yes |
* |
RtrnCapX |
return of capital, cash transfer |
|
yes |
* |
SellX |
sell, cash transfer |
|
yes |
* |
BuyX |
cash transfer, buy |
|
--- |
|
CGLong |
journal transaction (general) |
|
--- |
|
CGLongX |
journal transaction (general), cash transfer |
|
--- |
|
CGMid |
journal transaction (general) |
|
--- |
|
CGMidX |
journal transaction (general), cash transfer |
|
--- |
|
CGShort |
journal transaction (general) |
|
--- |
|
CGShortX |
journal transaction (general), cash transfer |
|
yes |
* |
Div |
journal transaction (general) |
|
yes |
* |
DivX |
journal transaction (general), cash transfer |
|
yes |
* |
IntInc |
journal transaction (general) |
|
yes |
* |
IntIncX |
journal transaction (general), cash transfer |
|
--- |
|
MargInt |
journal transaction (general) |
interest expense account |
--- |
|
MargIntX |
journal transaction (general), cash transfer |
interest expense account |
yes |
* |
MiscExp |
journal transaction (general) |
ask user where money came from (account) |
yes |
* |
MiscExpX |
journal transaction (general), cash transfer |
ask user where money came from (account) |
yes |
* |
MiscInc |
journal transaction (general) |
ask user where money came from (account) |
yes |
* |
MiscIncX |
journal transaction (general), cash transfer |
ask user where money came from (account) |
yes |
* |
StkSplit |
stock split |
|
yes |
* |
XIn |
cash transfer |
|
yes |
* |
XOut |
cash transfer |
|
yes |
* |
ShrsIn |
buy (or map to different type of event) |
ask user where money came from (account), present user with a list of possible transactions. Eventually we will try to guess the best match |
yes |
* |
ShrsOut |
sell (or map to different type of event) |
ask user where money goes to (account) |
|
|
|
|
|
|
|
store ignored and problematic data to be displayed to the user when finished. |
||
|
|
Have links for user to click and be displayed: |
||
|
|
Inserted Journal Entries |
||
|
|
Inserted Investment data |
||
|
|
Ignored Data |
//Psuedocode for importing qif file registers
//loop until all lines are read
while ($line != EOF)
//Input line and strip first character. character identifies line
SWITCH: ($character)
{
case '!'://Check to make sure "Bank" is next
break;
case 'D'://Get the date for a transaction
break;
case 'N'://Get the bank account number (check or deposit)
if 'D' //is next then debit is set and sub account is set to number.
break;
case 'P': //Payee Payer
break;
case 'A': //Address - IGNORE IT
break;
case 'L': //category. This will be the Sub Entity, Account, and/or sub account
//Check the line for ':'
switch (number)
{
case 0: //The line should refer to an account with no sub entity
break;
case 1: //The text before the : is sub entity and text after is account
break;
case 2://Text before is sub entity, between is account, last is SubAccount
break;
default: //Should not get here but if so then the data is not easily
//recognizable. Ask user
break;
}
break;
case '^': //Check to make sure all necessary data is filled in current trans
// and start new transaction.
break;
case 'T'://Amount
case 'U': //Don't know why there are two?
break;
case 'C': //Cleared
switch(text)
{
case '*': //Reconciled
break;
case 'X': //Cleared
break;
default: //Should not get here but if so then the data is not easily
//recognizable. Skip
break;
}
break;
case 'M': //Memo
break;
case 'S': //Accounts for rest of transaction
//next line should be a '$' read it in and apply it to this acount
break;
case 'E': //memo in split. Just add to .memo
break;
case '$': //Should not really get here because the amount should have been read
//in and allocating to an account already.
print("Error. Encountered a $ without an account to apply it to.");
break;
case '%': //Percentages? Not sure what to do?
print("Do not know how to deal with %.");
break;
case 'F': //Huh?
print("Do not know how to deal with F.");
break;
Default: print("Unrecognized character found! ");
print(character);
Break;
}