Where have I gone wrong

General FreeBASIC programming questions.
Post Reply
Gablea
Posts: 1104
Joined: Apr 06, 2010 0:05
Location: Northampton, United Kingdom
Contact:

Re: Where have I gone wrong

Post by Gablea »

@grindstone
Hi,
the tills and server run on either 10MB or 100MB network (depending on the switch that is in place)

I have been thinking about using a function that copy data from the Server (to for example c:\PoS\Data) and if the PoS can not see the shared drive on the windows Machine (or linux at some point) it will switch to local data files (and display a little icon showing no network)

I have some code from this forum that shows me how I can read the last updated date and time and i was going to use that to see what files are needed to be copied down to the local data folder at the end of each sale (as well as sending data to the Back office system)

I'm still trying to work out how I could make a universal function that would work will all the data files that my systems uses they are listed below

Age Refual File
Credit Note
Discount File
Gurantee File
Lottery File
Multivsaer File
Man Dept
No Sale Reason
PLU Menu
PLU List
Payout Reason
Product Libary
Product File - Code has been given but trying to get it to work with a universal interface for all files
Product Messages
Refund Reasons
Scanning Coupons
Cashier Database - Code has been given but trying to get it to work with a universal interface for all files
VAT Codes

As you can see it would be so much easier if I have a way of reading the files in with out having to create 100's of unique functions for each file.

I know It would be easier if I droped my DOS support but I just can not do that at the moment while I can get machines from NCR for less then $200 each and I can sell them with full software etc for $900+ (I do use FreeDOS on my Tills)
badidea
Posts: 2586
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Where have I gone wrong

Post by badidea »

Some of my thoughts:

A) Even if you can can connect from a msdos / freedos client to a mysql server, a significant change to the code is needed I think. mysql is normally not used for files but for individual records or values base on some query. Clear interfaces need to be define. The last time I looked at your code, it did not seem very well structured. Going from a bunch of files to a real database could be a lot of work.

B) An alternative to mysql could be your own client - server implementation via TCP/IP. This is doable, but some work. And the points mentioned at (A) are apply to this as well. So even more work.

C) A whole till could probably run on a Raspberry Pi with linux, which costs probably less then your msdos hardware. Then connecting to mysql is probably easier, but still the work required mentioned at (A).

There are probably work-arounds possible with the current local and centralised data files. Lock file access for a certain time to synchronise everything. Work with mutation files maybe. The locking mechanism / messaging could even be via a certain shared file. But in the end, such a system will likely give problems and probably difficult to maintain. The nice thing with using a real database, is that other tools can be used on this database. A web-interface or your own tool for analysis or accounting.

Do you have any experience with setting up a mysql database and with doing mysql queries?
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Where have I gone wrong

Post by jj2007 »

I start wondering if it wasn't sufficient to simply translate the csv into a two-dimensional string array. Ultra-fast and convenient.
Gablea
Posts: 1104
Joined: Apr 06, 2010 0:05
Location: Northampton, United Kingdom
Contact:

Re: Where have I gone wrong

Post by Gablea »

@badidea
Yes I use MySQL all the time with in the Visual Basic.net version of my EPoS systems.

I have managed to get Linux installed on the tills and yes I did even manage to get it to recall some data from a MySQL server. But I never seem to get it to recall the correct data (always seemed to bring back the previous sql query)

I know if I did move to MySQL interface for my till clents a lot of re working would be needed on the till source code and I’m not afraid to do that.
jj2007 wrote:I start wondering if it wasn't sufficient to simply translate the csv into a two-dimensional string array. Ultra-fast and convenient.
Could you explain more? If you require examples of the csv data files I can upload them to my web server.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Where have I gone wrong

Post by jj2007 »

Gablea wrote:Could you explain more? If you require examples of the csv data files I can upload them to my web server.
Yes, that would be a good idea.
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: Where have I gone wrong

Post by grindstone »

I didn't expect such a big amount of different data files. So here's a "one for all"-data access type:

Code: Select all

Type tRecord
	As ZString*40 recordName
	As Integer recordLength
	As ZString*2 returnType
End Type


'                                    return type-----------------------------------|
'                                    field length------------------------------|   |
'                                    field name---------------|                |   |
Dim Shared As tRecord userTable(1 To ...) = {Type <tRecord>("CashierPassword", 4, "s") _
                                           , Type <tRecord>("CashierName", 255, "s") _
                                           , Type <tRecord>("CashierNameReceipit", 40, "s") _
                                           , Type <tRecord>("ChangePassword", 1, "s") _
                                           , Type <tRecord>("RestrictRefund", 1, "s") _
                                           , Type <tRecord>("RestrictRefundValue", 10, "s") _
                                           , Type <tRecord>("UserCanOverrideLockout", 1, "s") _
                                           , Type <tRecord>("useraccesslevel", 255, "s") _
                                           , Type <tRecord>("DUMMY", 4, "s") _
                                           }
                                    
Dim Shared As tRecord productTable(1 To ...) = {Type <tRecord>("BarcodeNumber", 13, "s") _
                                              , Type <tRecord>("posdescription", 30, "s") _
                                              , Type <tRecord>("salelocation", 4, "s") _
                                              , Type <tRecord>("agerestricted", 4, "i") _
                                              , Type <tRecord>("agelimit", 2, "s") _
                                              , Type <tRecord>("pricetype", 1, "s") _
                                              , Type <tRecord>("retailprice", 10, "s") _
                                              , Type <tRecord>("vatcode", 1, "s") _
                                              , Type <tRecord>("vprint_guarantee_message", 4, "i") _
                                              , Type <tRecord>("print_guarantee_code", 6, "s") _
                                              , Type <tRecord>("displaymessage", 4, "i") _
                                              , Type <tRecord>("messagenumber", 6, "s") _
                                              , Type <tRecord>("sendtoppr", 4, "i") _
                                              , Type <tRecord>("requestserial", 4, "i") _
                                              , Type <tRecord>("itemnotallowed", 4, "i") _
                                              , Type <tRecord>("itemnotallowed_reason", 255, "s") _
                                              , Type <tRecord>("restrict_product_qty", 4, "i") _
                                              , Type <tRecord>("product_qty_allowed", 4, "i") _
                                              , Type <tRecord>("discount_not_allowed", 4, "i") _
                                              , Type <tRecord>("no_refund_allowed", 4, "i") _
                                              , Type <tRecord>("ask_for_qty_before_selling", 4, "i") _
                                              , Type <tRecord>("healthy_start_voucher_ok", 4, "i") _
                                              }


Type tDataAccess
	Dim record As String
	Dim As tRecord Ptr table
	Dim As Integer tableSize
	                                         
	Declare Function dataRead(fieldName As String) As String
	Declare Function dataRead(fieldName As String, fieldType As String) As Integer
	Declare Sub dataWrite(fieldName As String, value As String)
	Declare Sub dataWrite(fieldName As String, value As Integer)
	Declare Function getReclength() As Integer
	Declare Sub init(dataFile As String, extTable() As tRecord, thisArray() As tDataAccess)
	Declare Sub save(dataFile As String, thisArray() As tDataAccess)
End Type


Sub tDataAccess.init(dataFile As String, extTable() As tRecord, thisArray() As tDataAccess)
	Dim As Integer ff, recLen, count
	
	this.table = @extTable(1) 'pointer to field table
	this.tableSize = UBound(extTable) 'size of field table
		
	recLen = getReclength()
	
	ff = FreeFile
	Open datafile For Binary Access Read As #ff
	count = 0
	Do Until Eof(ff) 
		count += 1
		ReDim Preserve thisArray(count)
		thisArray(count) = thisArray(0) 'copy field table pointer and -size
		thisArray(count).record = Input(recLen, #ff) 'read one record from data file 
	Loop
	Close
End Sub

Sub tDataAccess.save(dataFile As String, thisArray() As tDataAccess)
	Dim As Integer ff
	
	ff = FreeFile
	Open dataFile For Output As #ff
	For x As Integer = 1 To UBound(thisArray)
		Print #ff, thisArray(x).record;
	Next
End Sub

Function tDataAccess.DataRead(fieldName As String) As String
	Dim As Integer x, start = 1
		
	If this.table = 0 Then Return "" 'no field table defined
	
	For x = 0 To this.tableSize - 1 'find requested field
		If LCase(fieldName) = LCase((this.table + x)->recordName) Then
			Exit For
		EndIf
		start += (this.table + x)->recordLength
	Next
	
	If x > tableSize Then 'record name not found
		Return ""
	ElseIf (this.table + x)->returnType <> "s" Then
		Return ""
	Else
		Return Mid(this.record, start, (this.table + x)->recordLength)
	EndIf
End Function

Function tDataAccess.dataRead(fieldName As String, fieldType As String) As Integer  
	Dim As Integer x, start = 1
	
	If this.table = 0 Then Return 0 'no field table defined
	
	For x = 0 To this.tableSize - 1 'find requested field
		If LCase(fieldName) = LCase((this.table + x)->recordName) Then
			Exit For
		EndIf
		start += (this.table + x)->recordLength
	Next
	
	If x > tableSize Then 'record name not found
		Return 0
	ElseIf (this.table + x)->returnType <> "i" Then
		Return 0
	Else
		Return Val(Mid(this.record, start, 4))
	EndIf
End Function

Sub tDataAccess.dataWrite(fieldName As String, value As String)
	Dim As Integer x, start = 1
	
	If this.table = 0 Then Return 'no field table defined
	
	For x = 0 To this.tableSize - 1 'find requested field
		If LCase(fieldName) = LCase((this.table + x)->recordName) Then
			Exit For
		EndIf
		start += (this.table + x)->recordLength
	Next
	If x > tablesize Then 'field not found
		Return
	ElseIf (this.table + x)->returnType <> "s" Then
		Return
	EndIf
	
	Mid(this.record, start, (this.table + x)->recordLength) = _
	Left(value + Space((this.table + x)->recordLength), (this.table + x)->recordLength)
	
End Sub

Sub tDataAccess.dataWrite(fieldName As String, value As Integer)
	Dim As Integer x, start = 1
	
	If this.table = 0 Then Return 'no field table defined
	
	For x = 0 To this.tableSize - 1 'find requested field
		If LCase(fieldName) = LCase((this.table + x)->recordName) Then
			Exit For
		EndIf
		start += (this.table + x)->recordLength
	Next
	If x > tablesize Then 'field not found
		Return
	ElseIf (this.table + x)->returnType <> "i" Then
		Return
	EndIf
		
	Mid(this.record, start, 4) = Right(String(4, Chr(0)) + Str(value), 4)
End Sub

Function tDataAccess.getReclength() As Integer
	Dim As Integer reclen
	Dim As tRecord Ptr rp = table
	
	For x As Integer = 0 To tableSize - 1
		reclen += (table + x)->recordLength
	Next
	
	Return reclen
End Function


ReDim As tDataAccess user(0), product(0)

'setup array
user(0).init("users.dat", userTable(), user()) 
'                  |           |         |_______"users" record array
'                  |           |_________________field table for "users"
'                  |_____________________________"users" data file
product(0).init("products.dat", productTable(), product())

'list of all user records
For x As Integer = 1 To UBound(user)
	With user(x)
		Print "        CashierPassword ";.dataRead("CashierPassword")
		Print "            CashierName ";.dataRead("CashierName")
		Print "    CashierNameReceipit ";.dataRead("CashierNameReceipit")
		Print "         ChangePassword ";.dataRead("ChangePassword")
		Print "         RestrictRefund ";.dataRead("RestrictRefund")
		Print "    RestrictRefundValue ";.dataRead("RestrictRefundValue")
		Print " UserCanOverrideLockout ";.dataRead("UserCanOverrideLockout")
		Print "        useraccesslevel ";.dataRead("useraccesslevel")
		Print "---------------------------------------------"
		Sleep
	End With
Next

'list of all product records
For x As Integer = 1 To UBound(product)
	With product(x)
		Print "             BarcodeNumber ";.dataRead("BarcodeNumber")
		Print "            posdescription ";.dataRead("posdescription")
		Print "              salelocation ";.dataRead("salelocation")
		Print "             agerestricted ";.dataRead("agerestricted", "i")
		Print "                  agelimit ";.dataRead("agelimit")
		Print "                 pricetype ";.dataRead("pricetype")
		Print "               retailprice ";.dataRead("retailprice")
		Print "                   vatcode ";.dataRead("vatcode")
		Print "  vprint_guarantee_message ";.dataRead("vprint_guarantee_message", "i")
		Print "      print_guarantee_code ";.dataRead("print_guarantee_code")
		Print "            displaymessage ";.dataRead("displaymessage", "i")
		Print "             messagenumber ";.dataRead("messagenumber")
		Print "                 sendtoppr ";.dataRead("sendtoppr", "i")
		Print "             requestserial ";.dataRead("requestserial", "i")
		Print "            itemnotallowed ";.dataRead("itemnotallowed", "i")
		Print "     itemnotallowed_reason ";.dataRead("itemnotallowed_reason")
		Print "      restrict_product_qty ";.dataRead("restrict_product_qty", "i")
		Print "       product_qty_allowed ";.dataRead("product_qty_allowed", "i")
		Print "      discount_not_allowed ";.dataRead("discount_not_allowed", "i")
		Print "         no_refund_allowed ";.dataRead("no_refund_allowed", "i")
		Print "ask_for_qty_before_selling ";.dataRead("ask_for_qty_before_selling", "i")
		Print "  healthy_start_voucher_ok ";.dataRead("healthy_start_voucher_ok", "i")
		Print "---------------------------------------------"
		Sleep
	End With
Next

'example for writing to array
product(1).datawrite("BarcodeNumber", "0123450")
product(1).datawrite("posdescription", "WODKA")

With product(1)
	Print "             BarcodeNumber ";.dataRead("BarcodeNumber")
	Print "            posdescription ";.dataRead("posdescription")
	Print "              salelocation ";.dataRead("salelocation")
	Print "             agerestricted ";.dataRead("agerestricted", "i")
	Print "                  agelimit ";.dataRead("agelimit")
	Print "                 pricetype ";.dataRead("pricetype")
	Print "               retailprice ";.dataRead("retailprice")
	Print "                   vatcode ";.dataRead("vatcode")
	Print "  vprint_guarantee_message ";.dataRead("vprint_guarantee_message", "i")
	Print "      print_guarantee_code ";.dataRead("print_guarantee_code")
	Print "            displaymessage ";.dataRead("displaymessage", "i")
	Print "             messagenumber ";.dataRead("messagenumber")
	Print "                 sendtoppr ";.dataRead("sendtoppr", "i")
	Print "             requestserial ";.dataRead("requestserial", "i")
	Print "            itemnotallowed ";.dataRead("itemnotallowed", "i")
	Print "     itemnotallowed_reason ";.dataRead("itemnotallowed_reason")
	Print "      restrict_product_qty ";.dataRead("restrict_product_qty", "i")
	Print "       product_qty_allowed ";.dataRead("product_qty_allowed", "i")
	Print "      discount_not_allowed ";.dataRead("discount_not_allowed", "i")
	Print "         no_refund_allowed ";.dataRead("no_refund_allowed", "i")
	Print "ask_for_qty_before_selling ";.dataRead("ask_for_qty_before_selling", "i")
	Print "  healthy_start_voucher_ok ";.dataRead("healthy_start_voucher_ok", "i")
	Print "---------------------------------------------"
	Sleep
End With

'saving arrays to file
user(0).save("usersSave2.dat", user())
'               |                |______record array
'               |_______________________file name to save to

product(0).save("productsSave2.dat", product())

? "OK"
Sleep
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Where have I gone wrong

Post by dodicat »

Nice work.
But bloody heck, I have just noticed why my save was not working properly as first, I had forgot to put the semi colon behind print #1, ...
Thus I gathered up everything in a string and saved the string.
silly silly.
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: Where have I gone wrong

Post by grindstone »

dodicat wrote:I had forgot to put the semi colon behind print #1, ...
Console yourself, I first forgot it, too. That's what test runs are good for. <grin>

BTW: I'd like to avoid the fieldType parameter in the dataRead(fieldName As String, fieldType As String) As Integer function. Is there a way to let the function dataRead(fieldName As String) return either a String or an Integer, according to the entry in the tRecord table ("s" or "i")? Overload doesn't work.
badidea
Posts: 2586
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Where have I gone wrong

Post by badidea »

Gablea wrote:Yes I use MySQL all the time with in the Visual Basic.net version of my EPoS systems.
I was just reading your previous topics on MySQL & MS-DOS with the conclusion that mysql-client on msdos close to impossible.
But, thinking out loud, what if you run a LAMP stack (Linux Apache MySQL PHP), and interface via web request / reply? Where PHP on the server does the MySQL calls. It maybe a bit crazy idea, but it could be done if MS-DOS can do web-requests. Or do I miss something?
Gablea wrote:I have managed to get Linux installed on the tills and yes I did even manage to get it to recall some data from a MySQL server. But I never seem to get it to recall the correct data (always seemed to bring back the previous sql query)
Sounds like a problem that should be solvable.
Gablea
Posts: 1104
Joined: Apr 06, 2010 0:05
Location: Northampton, United Kingdom
Contact:

Re: Where have I gone wrong

Post by Gablea »

@badidea
if I can find the old mySQL version of the PoS would you like me to post a sample of the code I am using?



I have acually found the project i was working on when I thought moving the PoS to the text files would be a good idea


http://www.algpos.co.uk/freebasic/MySQL_PoS.bas
Last edited by Gablea on Sep 24, 2018 21:40, edited 1 time in total.
badidea
Posts: 2586
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Where have I gone wrong

Post by badidea »

Gablea wrote:@badidea
if I can find the old mySQL version of the PoS would you like me to post a sample of the code I am using?
Yes, why not. I am certainly not an MySQL expert, but I have played with it in the past.
I plan the set-up a MySQL server anyway for other reasons (mediawiki installation).
Gablea
Posts: 1104
Joined: Apr 06, 2010 0:05
Location: Northampton, United Kingdom
Contact:

Re: Where have I gone wrong

Post by Gablea »

I have also uploaded to the server a data dump of one of my Databases


http://www.algpos.co.uk/freebasic/SparePoSDataFile.sql

i hope this can help if I can move to live MySQL interface and have it working then I would dump the DOS version as a TUI version of Linux would run with no sweat on a 600MHz with 512MB RAM (Plus the hard drive is like 60GB the only thing I would need to work out at some point of offline support)
sancho3
Posts: 358
Joined: Sep 30, 2017 3:22

Re: Where have I gone wrong

Post by sancho3 »

@Paul Doe:
I have had a chance to examine your code. Its slick. Very nice.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Where have I gone wrong

Post by dodicat »

grindstone wrote:
dodicat wrote:I had forgot to put the semi colon behind print #1, ...
Console yourself, I first forgot it, too. That's what test runs are good for. <grin>

BTW: I'd like to avoid the fieldType parameter in the dataRead(fieldName As String, fieldType As String) As Integer function. Is there a way to let the function dataRead(fieldName As String) return either a String or an Integer, according to the entry in the tRecord table ("s" or "i")? Overload doesn't work.
I note positions 0,2 and 6 all have length 4 but are strings.(Both tables)

something like
if (this.table + x)->recordLength=4 and x<>0 and x<>2 and x<>6 then (it is an integer)
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Where have I gone wrong

Post by jj2007 »

Gablea wrote:I have also uploaded to the server a data dump of one of my Databases
http://www.algpos.co.uk/freebasic/SparePoSDataFile.sql
Doesn't look like a csv file. MySQL can't export csv?
jj2007 wrote:
Gablea wrote:Could you explain more? If you require examples of the csv data files I can upload them to my web server.
Yes, that would be a good idea.
Post Reply