|POS file formats|
This page is for folks that wish to write 3rd party software to enhance my Cash Register software.
Please note that many things in the data files are restricted, for example passwords, sales figures, transaction numbers, taxes paid, PIN numbers, etc. If others know how to access those things then they would be able to write software to change those things. For example software could be written to to reduce the taxes collected for a day so that a store could pay less tax than is actually owed. This would then make the Cash Register software untrustworthy and therefore useless.
However if the data you need for your software is not accessible from the code below you can ask me to add it. If it is restricted I will politely refuse and if it is not I will add it to the listings below.
These file formats are in QuickBasic. In some instances I will also post formats that are in VisualBasic.
NOTE: In the code samples below the file name is set with FL$ = "KEYSHOP" Make sure that you use the file name of your register files when using the code.
Remember to open the .POS file as SHARED in the GLOBAL folder if the Cash Register program is being used over a network.
COLOR 15, 1: CLS DIM EMP$(56) FL$ = "KEYSHOP" OPEN FL$ + ".POS" FOR RANDOM AS 1 LEN = 80 FOR E = 0 TO 1 FOR A = 1 TO 3: FIELD 1, (A - 1) * 24 AS NULL$, 24 AS E$(A): NEXT FOR A = 0 TO 9 GET 1, A + 11 + E * 291 FOR B = 1 TO 3 C = A * 3 + B: IF C < 29 THEN EMP$(C + E * 28) = E$(B) NEXT B, A, E FOR A = 1 TO 19 FOR B = 0 TO 2 C = A + B * 19 IF C < 57 THEN LOCATE A, B * 26 + 1 PRINT USING "##.\ \"; C; EMP$(C); END IF NEXT B, A
Read this data from the LOCAL folder.
GBL = 0 = This is a LOCAL folder.
GBL = 1 = This is the GLOBAL folder.
COLOR 15, 1: CLS FL$ = "KEYSHOP" OPEN FL$ + ".POS" FOR RANDOM AS 1 LEN = 80 FIELD 1, 40 AS A$, 1 AS B$, 1 AS G$: GET 1, 8: REG$ = B$ PATH$ = LTRIM$(RTRIM$(A$)): IF INSTR(A$, CHR$(0)) THEN PATH$ = "": REG$ = "" GBL = SGN(ASC(G$)) CLOSE PRINT PATH$ PRINT GBL
The program below will read the data from the POLE.EXE file and display it on the screen.
The POLE.DAT file is read from the LOCAL folder.
COLOR 15, 1: CLS OPEN "POLE.DAT" FOR RANDOM ACCESS READ WRITE SHARED AS 1 LEN = 20 FIELD 1, 18 AS NUL$, 2 AS Z$: FIELD 1, 20 AS A$ FIELD 1, 15 AS STOCK$, 1 AS RD$, 2 AS TYPE$, 2 AS DIFF$ FIELD 1, 2 AS NOD$, 4 AS NET$, 4 AS TAX$, 4 AS TOTAL$, 1 AS UP$ P$ = "\" + SPACE$(18) + "\" 12 B$ = INKEY$: IF B$ = CHR$(27) THEN CLOSE : END GET 1, 3: DIFFERENT = CVI(DIFF$) IF DIFF <> DIFFERENT THEN DIFF = DIFFERENT GET 1, 1: LOCATE 1, 1: PRINT USING P$; A$; GET 1, 2: LOCATE 2, 1: PRINT USING P$; A$; GET 1, 3: LOCATE 3, 1: PRINT USING P$; STOCK$; TYPES = VAL(TYPE$): LOCATE 4, 1 IF TYPES = 0 THEN PRINT SPACE$(20) IF TYPES = 1 THEN PRINT USING P$; "PURCHASE"; IF TYPES = 2 THEN PRINT USING P$; "RETURN / PAYOUT"; RD = ASC(RD$): LOCATE 5, 1 IF RD = 0 THEN PRINT SPACE$(20) IF RD = 1 THEN PRINT USING P$; "DISCOUNT / REDUCTION"; IF RD = 2 THEN PRINT USING P$; "PRICE CHANGE"; END IF GET 1, 4: NODECIMAL = CVI(NOD$) IF NODECIMAL = 100 THEN PP$ = "##########" ELSE PP$ = "#######.##" IF UP$ = "1" THEN LOCATE 6, 1: PRINT " NET SALES"; USING PP$; CVL(NET$) / 100 * NODECIMAL LOCATE 7, 1: PRINT " TAX"; USING PP$; CVL(TAX$) / 100 * NODECIMAL LOCATE 8, 1: PRINT "TOTAL SALES"; USING PP$; CVL(TOTAL$) / 100 * NODECIMAL END IF LOCATE 10, 1: PRINT "PRESS [ESC] TO QUIT" GOTO 12
Q1) Line 1: Product description Line 2: Quanty X Single Price = Total
A2) Not neccessally. Record #1 contains the text that is supposed to be displayed on the top line of the pole display and record #2 contains the text that is supposed to be displayed on the second line of the pole display. For example before a transaction record #1 will contain "WELCOME TO...." and the second line will contain the store name.
Q2) What is "RD"? (used for, all possible values, etc) The real value is the ASCII code of the string RD?
A2) RD tells you if the data in records 1 and 2 are from a "discount / reduction" or a "price change." The REMOTE.EXE program uses the value of RD to decide if the information displayed from records 1 and 2 should be highlighted in a different color. Possible values are 0, 1, or 2.
Q3) What is "DIFF"? (used for, all possible values, etc)
A3) Every time the information in POLE.DAT is updated the value in DIFF is incremented by 1. Therefore when the value in DIFF changes it is time to update the pole display. Possible values are 0 to 32768 at which point the value is reset to 0.
Q4) What exactly does the CVL() function do, that it is used on the Net Total, Tax Rate, and Total? (Decoding of some sort? Is this an exclusively QBASIC function?) AND What is the CVI() function?
A4) I have no idea if QB is the only language that has the CVL( ) and CVI( ) functions because QB is the only language I know. However the deal is that QB can store numberic values in a compressed format. This serves two functions. First all the numbers of the same type (interger or single precision, etc.) all can be stored in the same length string (all intergers in 2 bytes, all long intergers in 4 bytes, etc.) which is really useful in random access files. The second function is that the numbers are much smaller to store. Remember that I come from a time before 100 gigabyte hard drives when a 360k floppy drive was the most you could hope for in storage. But anyway, following is some code that will replace the CVL( ) and CVI( ) commands.
A$ Is the number you are trying to convert.
X = 0
FOR A = 1 TO 4
E = ASC(MID$(A$, A, 1))
G = 256 ^ (A - 1)
X = X + E * G
A$ Is the number you are trying to convert.
X = 0
FOR A = 1 TO 2
E = ASC(MID$(A$, A, 1))
G = 256 ^ (A - 1)
X = X + E * G
Q5) What are the possible values for decimal/no decimal and what does each case mean?
A5) NOD can equal either 1 or 100. 100 means that there are no decimals displayed in numeric values. 1 means that decimals are displayed. This is only a concern with Net, Tax, and Total because values in records #1 and #2 are are handled by the POS program. The values that will be returned from Net, Tax, and Total will not have decimals when decoded by the program code above so to properly display the values this code is used.
PRINT USING "#####.##"; A / 100 * NOD
Q6) What is the "UP" value used for?
A6) When UP = 1 it means that the Net, Tax, and Total has been updated and should be redisplayed. Your program must reset the value of UP to zero in the POLE.DAT file.
The main file ends in the extension .TBL and contains all of the information in the stock table.
The first record in the stock table .TBL file contains the version number and the number of lines that are in the stock table
Remember to open the .POS file and the .TBL file as SHARED in the GLOBAL folder if the Cash Register program is being used over a network.
The following QuickBASIC code will read the stock table a line at a time and display the contends of each record on the screen.
DIM TB$(13) FL$ = "KEYSHOP": COLOR 15, 1: CLS OPEN FL$ + ".POS" FOR RANDOM AS 1 LEN = 80 FIELD 1, 70 AS A$, 1 AS B$: GET 1, 1 RCC = ASC(B$): CLOSE 1 :'Get number of lines that are supposed to be in the stock table. IF RCC = 32 THEN RCC = 15 RCC = (RCC - 10) * 1000 OPEN "R", 1, FL$ + ".TBL", 120: FIELD 1, 7 AS A$, 1 AS B$, 1 AS C$: GET 1, 1 RC = (ASC(C$) - 10) * 1000 :'Get number of lines that actually are in the stock table. IF A$ <> "VERSION" OR B$ <> CHR$(6) THEN PRINT "Not stock table version 6": END CLOSE 1 IF RCC < RC THEN RC = RCC OPEN "R", 2, FL$ + ".TBL", 120 FIELD 2, 24 AS TB$(0), 7 AS TB$(1), 1 AS TB$(5), 1 AS TB$(2), 4 AS TB$(3) FIELD 2, 37 AS NULL$, 4 AS TB$(4), 1 AS TB$(6), 4 AS TB$(7), 18 AS TB$(8) FIELD 2, 64 AS NULL$, 4 AS TB$(9), 4 AS TB$(10), 4 AS TB$(11), 30 AS TB$(12) FIELD 2, 106 AS NULL$, 4 AS TB$(13) FIELD 2, 120 AS TB$ FOR A = 1 TO RC GET 2, A + 1 CLS PRINT "RECORD"; A PRINT "STOCK NUMBER:"; RIGHT$(TB$(8), 14) :'Text PRINT "DESCRIPTION: "; TB$(0) :'Text PRINT "REGULAR PRICE:"; VAL(TB$(1)) / 100 :'Text PRINT "SALE PRICE:"; CVL(TB$(13)) / 100 :'Long interger x 100 PRINT "TAX RATE NUMBER: "; TB$(2) :'Text, refers to line in tax chart PRINT "CATEGORY NUMBER:"; ASC(TB$(5)) :'ASCII, refers to slot on category list PRINT "VENDOR NUMBER:"; ASC(TB$(6)) :'ASCII, refers to slot on vendor list PRINT "PIECES SOLD:"; CVL(TB$(3)) / 1000 :'Long interger x 1000 PRINT "VALUE SOLD:"; CVL(TB$(4)) / 100 :'Long interger x 100 PRINT "INVENTORY:"; CVL(TB$(7)) / 1000 :'Long interger x 1000 PRINT "COST:"; CVL(TB$(9)) / 100 :'Long interger x 100 PRINT "MODEL STOCK:"; CVL(TB$(10)) :'Long interger x 10 PRINT "WAREHOUSE PACK:"; CVL(TB$(11)) :'Long interger PRINT "VENDOR STOCK NUMBER: "; TB$(12) :'Text PRINT : PRINT "PRESS [ENTER] FOR NEXT LINE" PRINT : PRINT "PRESS [ESC] TO QUIT" 5 A$ = INKEY$: IF A$ = "" THEN 5 IF A$ = CHR$(27) THEN END NEXT CLOSE END
The other stock table file ends with the extension .IDX and contains an index of all the stock numbers in the stock table in condensed form. Since the .IDX file is relatively small the POS program can read it and keep the entire file in memory to use to quickly locate any item in the .TBL file.
This means that any program that makes a change in any item's stock number or moves, adds, or deletes any lines in the .TBL file must then re-index the .IDX file otherwise the POS program will no longer be able to find items in the .TBL file.
The following program will re-index the stock table. Remember that if you are using this program over a network that you must open the files as SHARED in the GLOBAL folder.
COLOR 15, 1: CLS ON ERROR GOTO ERRR: KILL PATH$ + FL$ + ".IDX": ON ERROR GOTO 0 FL$ = "KEYSHOP": COLOR 15, 1: CLS OPEN FL$ + ".TBL" FOR RANDOM AS 2 LEN = 80 FIELD 2, 70 AS A$, 1 AS B$: GET 2, 1 RCC = ASC(B$): CLOSE 2: 'Get number of lines that are supposed to be in the stock table. IF RCC = 32 THEN RCC = 15 RC = (RCC - 10) * 1000 OPEN "R", 2, FL$ + ".TBL", 120 FIELD 2, 46 AS NULL$, 18 AS STOCKNUMBER$ OPEN FL$ + ".IDX" FOR RANDOM AS 1 LEN = 2: FIELD 1, 2 AS P$ FOR A = 1 TO RC LOCATE 12, 57, 0: PRINT ABS(A - RC); GET 2, A + 1 STOCKNUMBER# = VAL(STOCKNUMBER$) IF STOCKNUMBER# < 1000000000 THEN P = STOCKNUMBER# ELSE P = VAL(MID$(LTRIM$(STR$(STOCKNUMBER#)), 3, 9)) END IF LSET P$ = MKI$(P MOD 65536 - 32768): PUT 1, A NEXT: CLOSE 2 END ERRR: RESUME NEXT: RETURN