' ------------------------------------------------------------
' Code generated automatically by Code Architects' VB Migration Partner
' ------------------------------------------------------------

Option Strict Off      ' Code migrated from VB6 has Option Strict disabled by default

<System.Runtime.InteropServices.ProgID("FMStocks_Bus.Broker")> _ 
<Transaction(TransactionOption.Required)> _
Public Class Broker
	Inherits ServicedComponent

	#Region "Constructor"
	
	'A public default constructor
	Public Sub New()
		' Add initialization code here
	End Sub
	
	#End Region
	
	#Region "Static constructor"
	
	' This static constructor ensures that the VB6 support library be initialized before using current class.
	Shared Sub New()
		EnsureVB6LibraryInitialization()
	End Sub
	
	#End Region

	Private Const m_modName As String = "FMStocks_Bus.Broker"
	Private Const m_errInsufficentFunds As Integer = &H80040E14I
	Private Const m_Commission As Decimal = 9.95

	' returns 0 on nothing to do, -1 on error, otherwise the TxID
	Public Function BuyStock(ByVal AccountID As Integer, ByVal Ticker As String, ByVal Shares As Integer) As Integer
		
		On Error GoTo errorHandler 
		
		Dim lngErr As Integer
		Dim lngTXID As Integer
		Dim lngPositionID As Integer
		Dim lngPrice As Integer
		
		Dim objTX As FMStocks_DB.Tx = Nothing
		Dim objTicker As FMStocks_DB.Ticker = Nothing
		Dim objbroker As FMStocks_DB.Broker = Nothing
		Dim objTXNew As FMStocks_DB.TxNew = Nothing
		
		objTX = New FMStocks_DB.Tx()
		objTicker = New FMStocks_DB.Ticker()
		objbroker = New FMStocks_DB.Broker()
		
		' first log the transaction
		lngTXID = objTX.AddBuyOrder(AccountID, Ticker, Shares)

		'Get the current price
		lngPrice = objTicker.GetPrice(Ticker) ' price in pennies
		
		On Error Resume Next 
		lngPositionID = objbroker.Buy(lngTXID, AccountID, Ticker, Shares, lngPrice, m_Commission)
		lngErr = Err.Number ' the next line resets Err.Number to 0, so we need to cache it
		On Error GoTo errorHandler 
		
		If lngPositionID = 0 And lngErr = m_errInsufficentFunds Then 
			' It's common that the user doesn't have enough funds.
			' Set the TransactionTypeID = 5 indicating insufficient funds
			
			' This guy runs as a separate transaction
			objTXNew = New FMStocks_DB.TxNew()
			objTXNew.SetTxType(lngTXID, FMStocks_TransactionType.Insufficient_Funds)
			
			GoTo InsufficientFundsHandler
		ElseIf lngPositionID = 0 Then 
			GoTo errorHandler ' some other error was thrown that we can't handle
		Else
			BuyStock = lngTXID ' The trade was handled
		End If
		
		objTX = Nothing
		objbroker = Nothing
		objTXNew = Nothing
		objTicker = Nothing
		
		VB6MtsMethods.GetObjectContext().SetComplete
		Exit Function
		
InsufficientFundsHandler:
		BuyStock = 0 ' Signify that we handled this error.
		' The caller should be aware that when this is returned,
		' the transaction has been aborted, the object deactivated.
		' An error isn't raised here (SP2) to be consistent with
		' prior versions.
		
		objTX = Nothing
		objTicker = Nothing
		objbroker = Nothing
		objTXNew = Nothing
		
		VB6MtsMethods.GetObjectContext().SetAbort
		Exit Function
		
errorHandler:
		BuyStock = -1
		objTX = Nothing
		objTicker = Nothing
		objbroker = Nothing
		objTXNew = Nothing
		
		VB6MtsMethods.GetObjectContext().SetAbort
		RaiseError(m_modName, "BuyStock(" & AccountID & "," & Ticker & "," & Shares & ")")
		
	End Function

	' returns 0 on nothing to do, -1 on error, otherwise the TxID
	Public Function SellStock(ByVal AccountID As Integer, ByVal Ticker As String, ByVal Shares As Integer) As Integer
		
		On Error GoTo errorHandler 
		
		Dim price As Decimal
		Dim txid As Integer
		Dim bSellretval As Boolean
		
		Dim objTX As FMStocks_DB.Tx = Nothing
		Dim objbroker As FMStocks_DB.Broker = Nothing
		Dim objTXNew As FMStocks_DB.TxNew = Nothing
		Dim objTicker As FMStocks_DB.Ticker = Nothing
		
		objTX = New FMStocks_DB.Tx()
		objbroker = New FMStocks_DB.Broker()
		objTicker = New FMStocks_DB.Ticker()
		
		txid = objTX.AddSellOrder(AccountID, Ticker, Shares)
		objTX = Nothing
		
		'Get the current price
		price = objTicker.GetPrice(Ticker) ' price in pennies
		
		On Error Resume Next 
		'ignore errors on this.
		bSellretval = objbroker.Sell(txid, price, m_Commission)
		
		On Error GoTo errorHandler 
		
		If bSellretval <> True Then 
			' This runs as a separate transaction
			objTXNew = New FMStocks_DB.TxNew()
			
			' User tried to sell shares they didn't own
			objTXNew.SetTxType(txid, FMStocks_TransactionType.Not_Enough_Shares)
			
			GoTo NotEnoughSharesHandler
		Else
			' We're responsible for removing the appropriate shares from their positions
			AdjustPositions(AccountID, Ticker, Shares)
			SellStock = txid
		End If
		
		objTX = Nothing
		objbroker = Nothing
		objTXNew = Nothing
		objTicker = Nothing
		
		VB6MtsMethods.GetObjectContext().SetComplete
		Exit Function
		
NotEnoughSharesHandler:
		SellStock = 0 ' Signify that we handled this error.
		' The caller should be aware that when this is returned,
		' the transaction has been aborted, the object deactivated.
		' An error isn't raised here (SP2) to be consistent with
		' prior versions.
		
		objTX = Nothing
		objbroker = Nothing
		objTXNew = Nothing
		objTicker = Nothing
		
		VB6MtsMethods.GetObjectContext().SetAbort
		Exit Function
		
errorHandler:
		SellStock = -1
		objTX = Nothing
		objbroker = Nothing
		objTXNew = Nothing
		objTicker = Nothing
		
		VB6MtsMethods.GetObjectContext().SetAbort
		RaiseError(m_modName, "SellStock(" & AccountID & "," & Ticker & "," & Shares & ")")
	End Function

	' no longer in used by buy or sell stocks
	' Used by ExecuteTrade program.
	' Returns 0 on nothing to do, -1 on error, otherwise the TxID
	Public Function ExecuteTransaction(ByVal txid As Integer) As Integer
		On Error GoTo errorHandler 
		
		Dim rs As ADODB.Recordset = Nothing
		Dim objTX As FMStocks_DB.Tx = Nothing
		Dim objTicker As FMStocks_DB.Ticker = Nothing
		Dim objbroker As FMStocks_DB.Broker = Nothing
		Dim o As FMStocks_DB.TxNew = Nothing
		
		objTX = New FMStocks_DB.Tx()
		objTicker = New FMStocks_DB.Ticker()
		objbroker = New FMStocks_DB.Broker()
		
		'information about the current transaction
		Dim AccountID As Integer
		Dim Ticker As String = ""
		Dim PositionID As Integer
		Dim price As Decimal
		Dim retval As Boolean
		
		Dim lerr As Integer

		' Get the Tx details
		rs = objTX.GetByID(txid)
		
		If (rs.EOF And rs.BOF) Then  Exit Function
		
		AccountID = rs.Fields("AccountID").Value
		Ticker = RTrim(rs.Fields("Ticker").Value)
		
		' Only execute buy or sell orders
		If rs.Fields("TransactionTypeID").Value <> 1 And rs.Fields("TransactionTypeID").Value <> 2 Then 
			ExecuteTransaction = 0
			VB6MtsMethods.GetObjectContext().SetComplete
			Exit Function
		End If
		
		'Get the current price
		price = objTicker.GetPrice(Ticker) ' price in pennies
		
		'Execute the trade
		If rs.Fields("TransactionTypeID").Value = 1 Then 
			' Buy order
			
			On Error Resume Next 
			PositionID = objbroker.Buy(txid, AccountID, Ticker, rs.Fields("shares").Value, price, m_Commission)
			lerr = Err.Number ' the next line resets Err.Number to 0, so we need to cache it
			On Error GoTo errorHandler 
			
			If PositionID = 0 And lerr = m_errInsufficentFunds Then 
				' It's common that the user doesn't have enough funds.
				' Set the TransactionTypeID = 5 indicating insufficient funds
				
				' This guy runs as a separate transaction
				o = New FMStocks_DB.TxNew()
				o.SetTxType(txid, FMStocks_TransactionType.Insufficient_Funds)
				o = Nothing
				
				GoTo InsufficientFundsHandler
			ElseIf PositionID = 0 Then 
				GoTo errorHandler ' some other error was thrown that we can't handle
			Else
				ExecuteTransaction = txid ' The trade was handled
			End If
		Else
			' Sell order
			
			On Error Resume Next 
			retval = objbroker.Sell(txid, price, m_Commission)
			lerr = Err.Number ' the next line resets Err.Number to 0, so we need to cache it
			On Error GoTo errorHandler 
			
			If retval = False Then 
				Err.Clear()
				
				' This runs as a separate transaction
				o = New FMStocks_DB.TxNew()
				o.SetTxType(txid, FMStocks_TransactionType.Not_Enough_Shares) ' User tried to sell shares they didn't own
				o = Nothing
				
				GoTo NotEnoughSharesHandler
			Else
				' We're responsible for removing the appropriate shares from their positions
				AdjustPositions(AccountID, Ticker, rs.Fields("shares").Value)
				ExecuteTransaction = txid
			End If
			
		End If
		
		VB6MtsMethods.GetObjectContext().SetComplete
		Exit Function
		
InsufficientFundsHandler:
NotEnoughSharesHandler:
		ExecuteTransaction = 0 ' Signify that we handled this error.
		' The caller should be aware that when this is returned,
		' the transaction has been aborted, the object deactivated.
		' An error isn't raised here (SP2) to be consistent with
		' prior versions.
		
		objTX = Nothing
		objTicker = Nothing
		objbroker = Nothing
		rs = Nothing
		
		VB6MtsMethods.GetObjectContext().SetAbort
		Exit Function
		
errorHandler:
		ExecuteTransaction = -1 'an invalid TransactionID used to flag an error.
		objTX = Nothing
		objTicker = Nothing
		objbroker = Nothing
		rs = Nothing
		o = Nothing
		
		VB6MtsMethods.GetObjectContext().SetAbort
		RaiseError(m_modName, "ExecuteTransaction(" & txid & ")")
		
	End Function

	'all errors are handled by the caller, ExecuteTransaction
	Private Sub AdjustPositions(ByVal AccountID As Integer, ByVal Ticker As String, ByVal Shares As Integer)
		Dim objPosition As FMStocks_DB.Position = New FMStocks_DB.Position()
		
		Dim rs As ADODB.Recordset = Nothing
		Dim posShares As Integer ' number of shares for the current position
		Dim origShares As Integer 'number of shares before sell
		Dim boolAdjusted As Boolean = False

		rs = objPosition.ListForAdjustment(AccountID, Ticker)
		Do While (Not (rs.EOF) And Shares > 0)
			posShares = rs.Fields("shares").Value
			boolAdjusted = True
			If posShares <= Shares Then 
				' we can delete this whole record
				rs.Delete()
				Shares -= posShares
			Else
				rs.Fields("shares").Value = posShares - Shares ' decrement current share amount by amount sold
				Shares = 0
			End If
			rs.MoveNext()
		Loop
		rs.UpdateBatch()
		rs.Close()
		rs = Nothing
	End Sub

End Class
