unit chart1;

{$mode ObjFPC}{$H+}
{$R *.lfm}

{ ============================================================================= }
{ INTERFACE - Gloablity                                                         }
{ ============================================================================= }
{	The "interface" section of a Pascal UNIT exports PUBLIC variables, constants	}
{ types, and routines, while the USES clause imports exported identifiers from	}
{ another UNITS interface section }

	interface

	{	EXTERNAL }
		uses
			Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls,
			ExtCtrls, LCLType, Math;
			function	l1_findAcct(AcctNo, All: Int64) : Int64; external;

	{	GLOBAL/PUBLIC -> all that follows until "implementation" }
		type

 			TCoa1 = class(TForm)
				Panel1												: TPanel;
					Label1											: TLabel;
						key_acctno								: TEdit;
				Panel2												: TPanel;
					Label3											: TLabel;
						description								: TEdit;
					Label4											: TLabel;
						flag1_combo								: TComboBox;
					Label5											: TLabel;
						flag2											: TEdit;
						flag2_spinner							: TUpDown;
					Label6											: TLabel;
						flag3											: TEdit;
						flag3_spinner							: TUpDown;
					Label7											: TLabel;
						flag4											: TEdit;
						flag4_spinner							: TUpDown;
					Label8											: TLabel;
						BalanceIndicator_combo		: TComboBox;
					Label9											: TLabel;
						cntlacctno								: TEdit;
					Label10											: TLabel;
						depreciation							: TEdit;
					Label11											: TLabel;
						unitprice									: TEdit;

				bSave													: TButton;
				bDelete												: TButton;
				bCancel												: TButton;

				ListView											: TListView;
				Panel3												: TPanel;

   		procedure FormCreate(Sender: TObject);
			procedure FormShow(Sender: TObject);
			procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
			procedure onKeyPress(Sender:TObject;var Key:char);
			procedure flag2_spinnerClick(Sender: TObject; Button: TUDBtnType);
			procedure flag3_spinnerClick(Sender: TObject; Button: TUDBtnType);
			procedure flag4_spinnerClick(Sender: TObject; Button: TUDBtnType);
			procedure bSaveClick(Sender: TObject);
			procedure bDeleteClick(Sender: TObject);
			procedure bCancelClick(Sender: TObject);
			procedure ListViewClick(Sender: TObject);
			private
			public
		end;

	var
		Coa1	: TCoa1;

{ ============================================================================= }
{ IMPLEMENTATION- private/Local                                                 }
{ ============================================================================= }
{	The "inplementation" section declares PRIVATE variables, constants, types, 		}
{ and routines. }

  Implementation
		uses
	  	Unit0, Chart2;

	{ NOTE:- procedures/functions declared in the implementation section must			}
	{	contain the keyword "forward" 																							}

		procedure COA_LISTVIEW(); forward;
  	procedure Key_Enable(); forward;
		procedure Details_Enable(); forward;
  	procedure init_accts(); forward;

		function  GET_ACCT() : boolean; forward;
		function	DETAILS_OKAY(): boolean; forward;

{ =============================================================================}
{ PROCEDURES/FUNCTIONS                                                         }
{ =============================================================================}

{ -----------------------------------------------------------------------------}
{ on Create Set ABLE/DISABLE fields		                                         }
{ -----------------------------------------------------------------------------}
	procedure TCoa1.FormCreate(Sender: TObject);
	begin

		{ Form to get Keystroke 1st	}
		KeyPreview := true;

	end;

{ -----------------------------------------------------------------------------}
{ Form Show														                                         }
{ -----------------------------------------------------------------------------}
	procedure TCoa1.FormShow(Sender: TObject);
	begin

		{ Only Print allowed for Consolidated Companies }
		If A01_ParameterNo = 3 then
			begin
				Coa2.ShowModal;
				Close;
			end // END BEGIN
		; // END IF

		Coa1.Caption := Format('%0.2d',[A01_Parameter]) + ' Chart Of Accounts';

		Key_Enable;
		GET_ACCT;
		COA_LISTVIEW();

		{ Account Types }
		flag1_Combo.Items.Clear;
		flag1_Combo.Items.Add('A ');
		flag1_Combo.Items.Add('X ');
		flag1_Combo.Items.Add('T ');
		flag1_Combo.Items.Add('C ');
		flag1_Combo.Items.Add('AB');
		flag1_Combo.Items.Add('CA');
		flag1_Combo.Items.Add('PA');
		flag1_Combo.Items.Add('BA');
		flag1_Combo.Items.Add('PL');
		flag1_Combo.Items.Add('DA');
		flag1_Combo.Items.Add('AS');
		flag1_Combo.Items.Add('TO');
		flag1_Combo.Items.Add('TC');

		{ Balance Indicator }
		BalanceIndicator_Combo.Items.Clear;
		BalanceIndicator_Combo.Items.Add('DR');
		BalanceIndicator_Combo.Items.Add('CR');

	end;

{ -----------------------------------------------------------------------------}
{ on form key down check for function keys                                     }
{ -----------------------------------------------------------------------------}
	procedure TCoa1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
	begin

	{	----------- }
	{	PF3 - Print }
	{	----------- }
		If  (key = 114)
		and (key_acctno.enabled) then
			begin
				Key := 0;
      	Coa2.ShowModal;
			end // END BEGIN
		; // End If

	{	------------ }
	{	PF5 - Accept }
	{	------------ }
		If  (key = 116)
		and (key_acctno.enabled)
		and (A01_ParameterNo <> 3 )then
			begin
        Key 			:= 0;
		    b01_recNo := 0;
				if GET_ACCT then
          Details_Enable
        ; // END IF
			end // END BEGIN
    ; // END IF

	end;

{ ----------------------------------------------------------------------------}
{ Field must be numeric																												}
{ ----------------------------------------------------------------------------}
	procedure TCoa1.onKeyPress(Sender:TObject;var Key:char);
	begin
		If not (Key in ['0'..'9', Char(VK_BACK), Char(VK_DELETE)]) then Key := #0;
	end;

{ -----------------------------------------------------------------------------}
{ Flag 2 spinner 	                                                             }
{ -----------------------------------------------------------------------------}
procedure TCoa1.flag2_spinnerClick(Sender: TObject; Button: TUDBtnType);
begin

		X := StrToIntDef(flag2.Text,0);

		If (Button = btNext) and (X < 4) then
			begin
				X := X + 1;
				flag2.Text	:= IntToStr(X);
			end
		; // END IF

		If (Button = btPrev) and (X > 1) then
			begin
				X := X - 1;
				flag2.Text	:= IntToStr(X);
				flag2.SetFocus;
			end
		; // END IF

end;

{ -----------------------------------------------------------------------------}
{ Flag 3 spinner 	                                                             }
{ -----------------------------------------------------------------------------}
procedure TCoa1.flag3_spinnerClick(Sender: TObject; Button: TUDBtnType);
begin

		X := StrToIntDef(flag3.Text,0);

		If (Button = btNext) and (X < 4) then
			begin
				X := X + 1;
				flag3.Text	:= IntToStr(X);
			end
			; // END IF

		If (Button = btPrev) and (X > 1) then
			begin
				X := X - 1;
				flag3.Text	:= IntToStr(X);
				flag3.SetFocus;
			end
		; // END IF

end;

{ -----------------------------------------------------------------------------}
{ Flag 4 spinner 	                                                             }
{ -----------------------------------------------------------------------------}
procedure TCoa1.flag4_spinnerClick(Sender: TObject; Button: TUDBtnType);
begin

		X := StrToIntDef(flag4.Text,0);

		If (Button = btNext) and (X < 4) then
			begin
				X := X + 1;
				flag4.Text	:= IntToStr(X);
			end
		; // END IF

		If (Button = btPrev) and (X > 0) then
			begin
				X := X - 1;
				flag4.Text	:= IntToStr(X);
				flag4.SetFocus;
			end
		; // END IF

end;

{ -----------------------------------------------------------------------------}
{ Selected from List View   	                                             		 }
{ -----------------------------------------------------------------------------}
	procedure TCoa1.ListViewClick(Sender: TObject);
	begin

		if(ListView.ItemIndex > -1) then
			begin
				b01_recNo := StrToIntDef(ListView.Selected.Caption,0);
				if  GET_ACCT then
						Details_Enable;
				; // END IF
 			end // END BEGIN
 		; // END IF

	end;

{ ----------------------------------------------------------------------------}
{ Details DELETE																															}
{ ----------------------------------------------------------------------------}
	procedure TCoa1.bDeleteClick(Sender: TObject);
 	begin

		case MessageDlgPos('Are you sure', mtConfirmation, [mbYes, mbNo, mbCancel],0,150,150) of
			mrCancel:;
			mrNO 		:;
			mrYes		:
				begin

					L0_CALL(c_B01,c_Delete,b01_recNo,0,b01_AllAccts);
					if RETURN_CODE = 0 then
						begin
							COA_LISTVIEW();
							Key_Enable;
						end // END BEGIN
					else
						case RETURN_CODE of
							40: MessageDlgPos('Account has active transactions',mtConfirmation, [mbOk],0,150,150);
							41: MessageDlgPos('Control Account has children',mtConfirmation, [mbOk],0,150,150);
							42: MessageDlgPos('Control Account has children',mtConfirmation, [mbOk],0,150,150);
							43: MessageDlgPos('Control Account does not exist',mtConfirmation, [mbOk],0,150,150);
						end // END CASE
					; // END IF
				end // END BEGIN
		end; // END CASE

end;

{ ----------------------------------------------------------------------------}
{ Details SAVE																																}
{ ----------------------------------------------------------------------------}
procedure TCoa1.bSaveClick(Sender: TObject);
begin

	If DETAILS_OKAY() then
		Key_Enable
	; // END IF

end;

{ ----------------------------------------------------------------------------}
{ Details CANCEL																															}
{ ----------------------------------------------------------------------------}
	procedure TCoa1.bCancelClick(Sender: TObject);
	begin
		key_Enable;
	end;

{ ----------------------------------------------------------------------------}
{ Key Enable																																	}
{ ----------------------------------------------------------------------------}
	procedure Key_Enable ();
	begin

	{	------------ }
	{	Enable KEY	 }
	{	------------ }
		Coa1.key_acctno.enabled									:= true;
		Coa1.key_acctno.SetFocus;

	{	--------------- }
	{	Disable DETAILS }
	{	--------------- }
		Coa1.description.enabled								:= false;
		Coa1.flag1_Combo.enabled								:= false;
		Coa1.flag2.enabled											:= false;
		Coa1.flag2_spinner.enabled							:= false;
		Coa1.flag3.enabled											:= false;
		Coa1.flag3_spinner.enabled							:= false;
		Coa1.flag4.enabled											:= false;
		Coa1.flag4_spinner.enabled							:= false;
		Coa1.balanceindicator_Combo.enabled			:= false;
		Coa1.cntlacctno.enabled									:= false;
		Coa1.depreciation.enabled								:= false;
		Coa1.unitprice.enabled									:= false;
		Coa1.bSave.enabled											:= false;
		Coa1.bDelete.enabled										:= false;
		Coa1.bCancel.enabled										:= false;

		Coa1.ListView.enabled										:= true;

	end;

{ ----------------------------------------------------------------------------}
{ Details Enable																															}
{ ----------------------------------------------------------------------------}
	procedure Details_Enable ();
	begin

	{	------------ }
	{	Disable KEY	 }
	{	------------ }
		Coa1.key_acctno.enabled									:= false;

	{	--------------- }
	{	Enable DETAILS	}
	{	--------------- }
		Coa1.description.enabled								:= true;
 		Coa1.description.SetFocus;

		Coa1.flag1_Combo.enabled								:= true;
		Coa1.flag2.enabled											:= true;
		Coa1.flag2_spinner.enabled							:= true;
		Coa1.flag3.enabled											:= true;
		Coa1.flag3_spinner.enabled							:= true;
		Coa1.flag4.enabled											:= true;
		Coa1.flag4_spinner.enabled							:= true;
		Coa1.balanceindicator_Combo.enabled			:= true;
		Coa1.cntlacctno.enabled									:= true;
		Coa1.depreciation.enabled								:= true;
		Coa1.unitprice.enabled									:= true;
		Coa1.bSave.enabled											:= true;
		Coa1.bDelete.enabled										:= true;
		Coa1.bCancel.enabled										:= true;

		Coa1.ListView.enabled										:= false;

	end;

{ -----------------------------------------------------------------------------}
{	populate ListView																														 }
{ -----------------------------------------------------------------------------}
	procedure COA_LISTVIEW();
	var
		Line	: TListItem;

	begin
		Coa1.ListView.Items.Clear;

		b01_AllAccts		:= l1_True;
		L0_Call(c_B01,c_Start,0,0,b01_AllAccts);
		If RETURN_CODE <> 0 then
			exit;

	{	----------------- }
	{	Transactions Loop	}
	{	----------------- }
		X	:= 0;
		while 1=1 do
			begin

				X := X + 1;

			{ get Record }
				L0_Call(c_B01,c_PreviousNext,1,0,b01_AllAccts);
				if RETURN_CODE <> 0 then
						break;

			{ Populate ListView }
				Line := Coa1.ListView.Items.add;
					Line.Caption:= Format('%0.3d',[B01_Record_NO]);
						Line.SubItems.Add(Format('%5d',[B01_AcctNo]));
						Line.SubItems.Add(B01_Description);

			end // END BEGIN
		; // END WHILE

	{ Get the details of the 1st one }
	{	----------------- }
	{	Empty List				}
	{	----------------- }
		If (X = 1) and (RETURN_CODE <> 0) then
			MessageDlgPos('No Account records exist as yet',mtConfirmation, [mbOk],0,150,150)
		else
			begin
				L0_Call(c_B01,c_Start,0,0,b01_AllAccts);
				Coa1.key_acctno.Text := IntToStr(B01_AcctNo);
				Coa1.ListView.Items[0].MakeVisible(true);
			end // END BEGIN
		; // End IF

	end;

//----------------------------------------------------------
//	GET_ACCT
//----------------------------------------------------------
	function GET_ACCT() : boolean;
  begin

	{ ------------------------- }
	{ Get The Key Values				}
	{-------------------------- }
		If Trim(Coa1.key_acctno.Text) = '' then
			X := 0
		else
			X := StrToIntDef(Coa1.key_acctno.Text,0)
		; // END IF

	//----------------------------------------------
	// F5 PRESSED -> Valid Key ?
	// Hitting PF5 always sets b01_recNo to zero
	// allowing us to know where this call came from
	//---------------------------------------------- 
		if b01_recNo = 0 then

			begin

				if X > 59998 then
					begin
						MessageDlgPos('Account No must be less than 59999',mtConfirmation, [mbOk],0,150,150);
						GET_ACCT := false;
						exit;
					end // END BEGIN
				; // END IF

				if X < 10000 then
					begin
						MessageDlgPos('Account No must be greater than 9999',mtConfirmation, [mbOk],0,150,150);
						GET_ACCT := false;
						exit;
					end // END BEGIN
				; // END BEGIN

		{ ------------------------- }
		{ Find Account							}
		{ ------------------------- }
		{	When used for the spinners this call will send the last account no back	}
		{ at EOF. We don't really want that here so check the RETURN_CODE for EOF	}
			b01_recNo := L0_findAcct(X,l1_True);
			if RETURN_CODE <> 0 then b01_recNo := 0;

		{ ------------------------- }
		{ EXISTING OR NEW						}
		{ ------------------------- }
			if b01_recNo = 0 then
			{ NEW }
				begin
					newRecord := true;
					init_accts();
					GET_ACCT := true;
					exit;
				end // END BEGIN
			else
				newRecord := false;
			; // END IF

			end // END BEGIN

	else
	{ ------------------------- }
	{ from ListView 						}
	{-------------------------- }
		begin
			newRecord := false;
			L0_CALL(c_B01,c_Read,b01_recNo,0,b01_AllAccts);
			Coa1.key_acctno.Text := IntToStr(B01_AcctNo);
		end // END BEGIN

	; // END IF

	//-------
	//Details
	//------- 
		Coa1.description.Text		:= B01_Description;

		Str := B01_Flag1;
		case Str of
			'A ' 	: Coa1.flag1_Combo.ItemIndex := 00;
			'X '	: Coa1.flag1_Combo.ItemIndex := 01;
			'T '	: Coa1.flag1_Combo.ItemIndex := 02;
			'C '	: Coa1.flag1_Combo.ItemIndex := 03;
			'AB'	: Coa1.flag1_Combo.ItemIndex := 04;
			'CA'	: Coa1.flag1_Combo.ItemIndex := 05;
			'PA'	: Coa1.flag1_Combo.ItemIndex := 06;
			'BA'	: Coa1.flag1_Combo.ItemIndex := 07;
			'PL'	: Coa1.flag1_Combo.ItemIndex := 08;
			'DA'	: Coa1.flag1_Combo.ItemIndex := 09;
			'AS'	: Coa1.flag1_Combo.ItemIndex := 10;
			'TO'	: Coa1.flag1_Combo.ItemIndex := 11;
			'TC'	: Coa1.flag1_Combo.ItemIndex := 12;
		else
			Str := 'WTF';
		end; // END CASE

		Coa1.Flag2.Text := IntToStr(B01_Flag2);
		Coa1.Flag3.Text := IntToStr(B01_Flag3);
		Coa1.Flag4.Text := IntToStr(B01_Flag4);

		Str := B01_BalanceIndicator;
		case Str of
			'DR' 	: Coa1.balanceindicator_Combo.ItemIndex := 00;
			'CR'	: Coa1.balanceindicator_Combo.ItemIndex := 01;
		end; // END CASE

		Coa1.cntlacctno.Text 		:= IntToStr(B01_CntlAcctNo);
		Coa1.depreciation.Text	:= IntToStr(B01_Depreciation);
		Coa1.unitprice.Text			:= w_B01_UnitPrice;

		GET_ACCT := true;

end;

{ ----------------------------------------------------------------------------}
{ INIT_ACCOUNT																																}
{ ----------------------------------------------------------------------------}
	procedure init_accts();
	begin

	{ ----- }
	{ KEY		}
	{ ----- }
		B01_AcctNo	:= StrToIntDef(Coa1.key_acctno.Text,0);

	{ --------- }
	{ DETAILS		}
	{ --------- }
		Coa1.description.Text							:='';
		Coa1.Flag1_Combo.Text							:='A ';
		Coa1.Flag2.Text										:='1';
		Coa1.Flag3.Text										:='1';
		Coa1.Flag4.Text										:='0';

    If (b01_recNo = 0) then
			case B01_AcctNo of
				10000..19999 : Coa1.balanceindicator_Combo.Text	:='CR';
				20000..29999 : Coa1.balanceindicator_Combo.Text	:='DR';
				30000..39999 : Coa1.balanceindicator_Combo.Text	:='CR';
				40000..49999 : Coa1.balanceindicator_Combo.Text	:='CR';
				50000..59999 : Coa1.balanceindicator_Combo.Text	:='DR';
			end; // END CASE
    ; // END IF

		Coa1.cntlacctno.Text							:='0';
		Coa1.depreciation.Text						:='0';
		Coa1.unitprice.Text								:='0000.0000';

	end;

{ ----------------------------------------------------------------------------}
{ DETAILS OKAY																																}
{ ----------------------------------------------------------------------------}
	function DETAILS_OKAY(): boolean;
	begin

		DETAILS_OKAY := false;

	{ ------------ }
	{ Valid Data ? }
	{ ------------ }

	{ DESCRIPTION }
		if ansistring.IsNullOrWhiteSpace(Coa1.description.Text) then
			begin
				MessageDlgPos('Please entera description',mtConfirmation, [mbOk],0,150,150);
				exit;
			end // END BEGIN
		else
			B01_Description := Format('%-30s',[Coa1.description.Text]);
		; // END IF


	{ flag1_Combo }
		X := Coa1.flag1_Combo.ItemIndex;
 		case X of
			00	: B01_Flag1 := 'A ';
			01	: B01_Flag1 := 'X ';
			02	: B01_Flag1 := 'T ';
			03	: B01_Flag1 := 'C ';
			04	: B01_Flag1 := 'AB';
			05	: B01_Flag1 := 'CA';
			06	: B01_Flag1 := 'PA';
			07	: B01_Flag1 := 'BA';
			08	: B01_Flag1 := 'PL';
			09	: B01_Flag1 := 'DA';
			10	: B01_Flag1 := 'AS';
			11	: B01_Flag1 := 'TO';
			12	: B01_Flag1 := 'TC';
		end; // END CASE

	{ FLAG2,3,4 }
		If (coa1.flag2.Text < '1') or (coa1.flag2.Text > '4') then
			begin
				MessageDlgPos('Flag2 must be between 1 and 4',mtConfirmation, [mbOk],0,150,150);
				exit;
			end // END BEGIN
		else
			B01_Flag2	:=StrToIntDef(coa1.flag2.Text,0)
		; // END IF

		If (coa1.flag3.Text < '1') or (coa1.flag3.Text > '4') then
			begin
				MessageDlgPos('Flag3 must be between 1 and 4',mtConfirmation, [mbOk],0,150,150);
				exit;
			end // END BEGIN
		else
			B01_Flag3	:=StrToIntDef(coa1.flag3.Text,0)
		; // END IF

		If (coa1.flag4.Text < '0') or (coa1.flag4.Text > '4') then
			begin
				MessageDlgPos('Flag4 must be between 0 and 4',mtConfirmation, [mbOk],0,150,150);
				exit;
			end // END BEGIN
		else
			B01_Flag4	:=StrToIntDef(coa1.flag4.Text,0)
		; // END IF

	//BALANCE INDICATOR
	//	Note: The Balance indicator only facilitates the Trading Statement ie:
	//		DR Opening Stock
	//		DR Purchases
	//		CR Closing Stock
		X := Coa1.balanceindicator_Combo.ItemIndex;
 		case X of
			00	: B01_BalanceIndicator	:= 'DR';
			01	: B01_BalanceIndicator	:= 'CR';
		end; // END CASE

	{ CONTROL ACCOUNT }
		X := StrToIntDef(Coa1.cntlacctNo.Text,0);
		if (X = B01_AcctNo) then
			begin
				MessageDlgPos('Control Account cannot refer to itself',mtConfirmation, [mbOk],0,150,150);
				exit;
			end // END BEGIN
		else
			B01_CntlAcctNo := X;
		; // END IF

	{ DEPRECIATION }
		B01_Depreciation := StrToIntDef(Coa1.depreciation.Text,0);

	{ UNITPRICE }
		w_B01_UnitPrice := Coa1.unitprice.Text;

	{ --------- }
	{ Proceed ? }
	{ --------- }
		L0_Call(c_B01,c_Write,b01_recNo,0,b01_AllAccts);
		if RETURN_CODE = 0 then
			begin
				DETAILS_OKAY := true;
				COA_LISTVIEW();
			end // END BEGIN
		else
			begin
				case RETURN_CODE of
						41: MessageDlgPos('Control Account has children',mtConfirmation, [mbOk],0,150,150);
						42: MessageDlgPos('Control Account has children',mtConfirmation, [mbOk],0,150,150);
						43: MessageDlgPos('Control Account does not exist',mtConfirmation, [mbOk],0,150,150);
				end; // END CASE
			end // END BEGIN
		; // End If
	end;

{ -----------------------------------------------------------------------------}
{ End Of Program						 	                                             		 }
{ -----------------------------------------------------------------------------}
end.

