{*******************************************************} { } { Responsive Software http://www.responsive.co.nz } { } { Copyright (c) 2003-2006 Responsive Software Limited } { } {*******************************************************} unit Accounts; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, BaseFrameUnit, StdCtrls, Grids, ComCtrls, ExtCtrls, DatabaseObjects; type TAccountsFrame = class(TBaseFrame) Label1: TLabel; AccountComboBox: TComboBox; Bevel1: TBevel; EntriesStringGrid: TStringGrid; StatusLabel: TLabel; EmailButton: TButton; PrintButton: TButton; EntryButton: TButton; BalanceLabel: TLabel; BalanceHeadingLabel: TLabel; DescriptionLabel: TLabel; AccountTypeHeadingLabel: TLabel; AccountTypeLabel: TLabel; DescriptionHeadingLabel: TLabel; PeriodHeadingLabel: TLabel; PeriodLabel: TLabel; HeadingLabel: TLabel; HeadingShape: TShape; FindButton: TButton; NextButton: TButton; SummaryButton: TButton; procedure EmailButtonClick(Sender: TObject); procedure PrintButtonClick(Sender: TObject); procedure EntryButtonClick(Sender: TObject); procedure EntriesStringGridClick(Sender: TObject); procedure AccountComboBoxSelect(Sender: TObject); procedure EntriesStringGridDblClick(Sender: TObject); procedure EntriesStringGridKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure EntriesStringGridDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); procedure AccountComboBoxKeyPress(Sender: TObject; var Key: Char); procedure FindButtonClick(Sender: TObject); procedure NextButtonClick(Sender: TObject); procedure SummaryButtonClick(Sender: TObject); private { Private declarations } IgnoreChangeEvents : boolean; // set this to true when updating controls in code // Account refers to the account currently being viewed // it is a copy and not the one in the global Accounts collection Account : TAccount; // Entry refers to the entry currently being viewed Entry : TEntry; FindText : string; procedure SetEntry; procedure UpdateControls; procedure UpdateEntriesStringGrid; procedure UpdateControlStates; procedure SwitchToCombinedEntry; public { Public declarations } procedure UpdateDisplay; procedure UpdateComboBoxes (Full : boolean); override; procedure Setup; override; procedure HandleF6; override; procedure ClearDisplay; procedure ShowAccount (AccountId : int64); procedure PositionEntriesStringGrid (EntryId : int64); end; implementation uses GeneralUtilities, DatabaseManager, Globals, Base, Utilities, Main, Entries, PromptString; {$R *.dfm} procedure TAccountsFrame.HandleF6; begin MainForm.SwitchToFrame('Cashbooks'); end; procedure TAccountsFrame.Setup; begin SetUpStringGrid(EntriesStringGrid,[ 'Date', 'Description', 'Debit', 'Credit', 'Other A/c' ],[ 12, // Date 37, // Description 13, // Debit 13, // Credit 25 // Other A/c ]); // create and initialise objects EntriesStringGrid.Row := 1; UpdateComboBoxes(false); UpdateDisplay; end; procedure TAccountsFrame.SetEntry; var Index : integer; begin if Account = nil then begin Entry := nil; Exit; end; if WorkstationConfiguration.RecentEntryFirst then Index := Account.EntriesInPeriod.Count - EntriesStringGrid.Row else Index := EntriesStringGrid.Row - 1; if Index < Account.EntriesInPeriod.Count then Entry := TEntry(Account.EntriesInPeriod[Index]) else Entry := nil; end; procedure TAccountsFrame.UpdateComboBoxes (Full : boolean); var i : integer; begin AccountComboBox.Items.Clear; for i := 0 to Globals.Accounts.Count - 1 do if TAccount(Globals.Accounts[i]).CompanyId = WorkstationConfiguration.CompanyId then AccountComboBox.Items.Add(TAccount(Globals.Accounts[i]).ComboBoxDisplayString); end; procedure TAccountsFrame.UpdateControls; begin IgnoreChangeEvents := true; if Account <> nil then begin AccountComboBox.ItemIndex := AccountComboBox.Items.IndexOf(Account.ComboBoxDisplayString); DescriptionLabel.Caption := Account.Description; AccountTypeLabel.Caption := Account.AccountTypeString + ' - ' + Account.AccountTypeDescription; PeriodLabel.Caption := WorkstationConfiguration.AccountingPeriodString; DescriptionHeadingLabel.Visible := true; AccountTypeHeadingLabel.Visible := true; BalanceHeadingLabel.Visible := true; PeriodHeadingLabel.Visible := true; end else begin AccountComboBox.ItemIndex := -1; DescriptionLabel.Caption := ''; AccountTypeLabel.Caption := ''; PeriodLabel.Caption := ''; DescriptionHeadingLabel.Visible := false; AccountTypeHeadingLabel.Visible := false; BalanceHeadingLabel.Visible := false; PeriodHeadingLabel.Visible := false; end; IgnoreChangeEvents := false; end; procedure TAccountsFrame.UpdateEntriesStringGrid; var i : integer; begin // display entries in string grid if Account = nil then begin EntriesStringGrid.RowCount := 2; // clear details on last row for i := 0 to EntriesStringGrid.ColCount - 1 do EntriesStringGrid.Cells[i,1] := ''; // update balance labels BalanceLabel.Caption := ''; end else begin if Account.EntriesInPeriod.Count = 0 then begin EntriesStringGrid.RowCount := 2; // clear details on last row for i := 0 to EntriesStringGrid.ColCount - 1 do EntriesStringGrid.Cells[i,Account.EntriesInPeriod.Count+1] := ''; end else EntriesStringGrid.RowCount := Account.EntriesInPeriod.Count + 1; // don't update string grid here but display info as required // directly from draw cell event to save time EntriesStringGrid.Repaint; // update balance labels BalanceLabel.Caption := Account.AccountingPeriodBalanceString; end; end; procedure TAccountsFrame.UpdateControlStates; begin AccountComboBox.Enabled := true; // display status label StatusLabel.Caption := ''; SummaryButton.Enabled := Account <> nil; FindButton.Enabled := (Account <> nil) and (Entry <> nil); NextButton.Enabled := (Account <> nil) and (Entry <> nil) and (FindText <> ''); EmailButton.Enabled := Account <> nil; PrintButton.Enabled := Account <> nil; EntryButton.Enabled := (Account <> nil) and (Entry <> nil); end; procedure TAccountsFrame.UpdateDisplay; begin UpdateEntriesStringGrid; SetEntry; UpdateControls; UpdateControlStates; end; procedure TAccountsFrame.ClearDisplay; begin Account := nil; EntriesStringGrid.Row := 1; UpdateDisplay; end; procedure TAccountsFrame.SwitchToCombinedEntry; var EntriesFrame : TEntriesFrame; begin // switch to entries frame and allow user to edit combined entries EntriesFrame := MainForm.EntriesFrame; if EntriesFrame.CanClose then begin MainForm.SwitchToFrame('Entries'); EntriesFrame.ShowCombinedEntry(Entry.CombinedEntryId); EntriesFrame.PositionEntriesStringGrid(Entry.Id); end else MessageDlg('Entry in progress',mtError,[mbOk],0); end; procedure TAccountsFrame.ShowAccount (AccountId : int64); begin if (Account = nil) or (Account.Id <> AccountId) then begin Account := AccountsCache.GetAccount(AccountId); EntriesStringGrid.Row := 1; UpdateDisplay; end; end; procedure TAccountsFrame.PositionEntriesStringGrid (EntryId : int64); var i : integer; begin for i := 0 to Account.EntriesInPeriod.Count - 1 do begin if Account.EntriesInPeriod[i].Id = EntryId then begin if WorkstationConfiguration.RecentEntryFirst then EntriesStringGrid.Row := Account.EntriesInPeriod.Count - i else EntriesStringGrid.Row := i + 1; Exit; end; end; EntriesStringGrid.Row := 1; end; {******************************************************************************} procedure TAccountsFrame.EmailButtonClick(Sender: TObject); begin if Account <> nil then Account.Email; end; procedure TAccountsFrame.PrintButtonClick(Sender: TObject); begin if Account <> nil then Account.Print; end; procedure TAccountsFrame.SummaryButtonClick(Sender: TObject); begin if Account <> nil then Account.PrintSummary; end; procedure TAccountsFrame.EntryButtonClick(Sender: TObject); begin if Entry <> nil then SwitchToCombinedEntry; end; procedure TAccountsFrame.FindButtonClick(Sender: TObject); var EntryId : int64; begin if PromptStringForm.Prompt(false,'Enter Search String','Description') then begin FindText := PromptStringForm.Value; EntryId := Account.FindNextEntryInPeriod(FindText,Entry,WorkstationConfiguration.RecentEntryFirst); if EntryId <> 0 then PositionEntriesStringGrid(EntryId) else ShowMessage('Entry not found'); end; end; procedure TAccountsFrame.NextButtonClick(Sender: TObject); var EntryId : int64; begin EntryId := Account.FindNextEntryInPeriod(FindText,Entry,WorkstationConfiguration.RecentEntryFirst); if EntryId <> 0 then PositionEntriesStringGrid(EntryId) else ShowMessage('Entry not found'); end; procedure TAccountsFrame.EntriesStringGridClick(Sender: TObject); begin SetEntry; UpdateControls; UpdateControlStates; end; procedure TAccountsFrame.EntriesStringGridDblClick(Sender: TObject); begin if Entry <> nil then SwitchToCombinedEntry; end; procedure TAccountsFrame.EntriesStringGridKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = VK_RETURN then begin if Entry <> nil then SwitchToCombinedEntry; Key := 0; end; end; procedure TAccountsFrame.EntriesStringGridDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); var Entry : TEntry; Text : string; function NewMonth : boolean; var PreviousEntry : TEntry; ThisDay, ThisMonth, ThisYear : word; PreviousDay, PreviousMonth, PreviousYear : word; begin if WorkstationConfiguration.RecentEntryFirst then PreviousEntry := TEntry(Account.EntriesInPeriod[Account.EntriesInPeriod.Count - ARow - 1]) else PreviousEntry := TEntry(Account.EntriesInPeriod[ARow - 2]); if PreviousEntry = nil then Result := true else begin DecodeDate(Entry.Date,ThisYear,ThisMonth,ThisDay); DecodeDate(PreviousEntry.Date,PreviousYear,PreviousMonth,PreviousDay); if (ThisMonth <> PreviousMonth) or (ThisYear <> PreviousYear) then Result := true else Result := false; end; end; begin if Account <> nil then begin if WorkstationConfiguration.RecentEntryFirst then Entry := TEntry(Account.EntriesInPeriod[Account.EntriesInPeriod.Count - ARow]) else Entry := TEntry(Account.EntriesInPeriod[ARow - 1]); if Entry <> nil then begin // set the brush color if gdSelected in State then EntriesStringGrid.Canvas.Brush.Color := clHighlight else if NewMonth then EntriesStringGrid.Canvas.Brush.Color := DarkenColor(EntriesStringGrid.Color) else EntriesStringGrid.Canvas.Brush.Color := EntriesStringGrid.Color; // format the text if ACol = 0 then Text := FormatDate(Entry.Date) else if ACol = 1 then Text := Entry.Description else if ACol = 2 then begin if Entry.Debit then Text := FormatCurrencyForDisplay(Entry.AbsoluteAmount) else Text := ''; end else if ACol = 3 then begin if Entry.Credit then Text := FormatCurrencyForDisplay(Entry.AbsoluteAmount) else Text := ''; end else if ACol = 4 then Text := Entry.OtherAccountName; // output the text EntriesStringGrid.Canvas.TextRect(Rect,Rect.Left+2,Rect.Top+2,Text); end; end; end; {***** AccountComboBox event handling *****************************************} procedure TAccountsFrame.AccountComboBoxKeyPress(Sender: TObject; var Key: Char); begin if Key = Char(VK_RETURN) then begin if Trim(TComboBox(Sender).Text) = '' then Exit; TBaseForm(Parent).GoToNextControl; Key := Char(0); end; end; procedure TAccountsFrame.AccountComboBoxSelect(Sender: TObject); var AccountId : int64; begin AccountId := Globals.Accounts.GetIdFromComboBoxDisplayString(TComboBox(Sender).Text); if (Account = nil) or (Account.Id <> AccountId) then begin Account := AccountsCache.GetAccount(AccountId); EntriesStringGrid.Row := 1; UpdateDisplay; end; end; {******************************************************************************} end.