{****************************************************************************
 ***                                                                      ***
 *** New Fabbo Singing Dancing OOP                                        ***
 ***                            GOODS IN                                  ***
 ***                                                                      ***
 *** M Hill                                                      Nov 1994 ***
 ****************************************************************************}
{For placing GoodsIns with suppliers.  Based on invoices - sales GoodsIns - for
 nodes, etc}

{$I compdirs}  {Compiler directives}
unit kGoodsIn;

INTERFACE

uses 	jimmys,
			objects,
			edit, views,
			output,
			global,
			displays, menus, tasks,
			notes,
			nodes,
      kinvoice, kinvnode,
			dattime, inpdnt;

{*****************************
 ***  GoodsIn              ***
 *****************************}
const
 TGoodsInSize = 50;

type
 PGoodsIn = ^TGoodsIn;
 TGoodsIn = object(TJimmy)

    RecDate : TDate;

		Ref				: string[5];

		FromWho    : longint;

		ItemTree : TNodeTree;

		Comment   : PNoteData;            {Text on GoodsIn}

    StockUpdated : boolean;

	 {-- Methods --}
	 constructor Init(Params : pointer);
	 procedure   CommonInit; virtual;    {Extra initialisation, shared between init & load}
	 destructor Done; virtual;

	 {Display}
	 function DisplayLine(Maxlen : integer; View : word) : string; virtual;

	 {DataBase}
	 constructor Load(var S : TStream);
	 procedure   Store(var S : TSTream);              virtual;
		function    GetKey : word;                        virtual;

		procedure MakeEditBox(var EditBox : PEditBox; Caller : PView); virtual;
		procedure StoreSelf; virtual;

		procedure SetFormCodes(Output : PoutputStream; Prefix : String); virtual;
		function Print(prType : word; Output : Poutputstream) : word; virtual;

    procedure UpdateStock;

 end;

function CreateGoodsIn(P : pointer) : pointer; far;


const
	{--- Required for Stream ----}
	RGoodsIn : TStreamRec = (
		ObjType : srGoodsIn;
		VmtLink : Ofs(TypeOf(TGoodsIn)^);
		Load : @TGoodsIn.Load;
		Store : @TGoodsIn.Store
	);

var GoodsInNewMenu : PMenu;


IMPLEMENTATION

uses  files,
			minilib,
			errors, messages,
			kamapp, app,
      jimhooks,
			setup,
			dialogs,
      idindex,  {id refs etc}
      kproduct,
			khistory, {for adding to new menu}
			inpdir, kdirctry;



{***********************************************************************
 ***                                                                 ***
 ***                      GoodsIn                                      ***
 ***                                                                 ***
 ***********************************************************************}
function CreateGoodsIn; begin CreateGoodsIn := New(PGoodsIn, Init(P)); end;

{--- Initialise - set ptrs to SC ---}
constructor TGoodsIn.Init;
begin
	inherited Init;

	if Params <> nil then FromWho := Plongint(Params)^ else FromWho :=-1;

	Ref := '*NEW*';

  RecDate.SetToToday;

	StockUpdated := False;
end;

procedure TGoodsIn.CommonInit;  {Init shared betweeen load and init above}
begin
	inherited CommonInit;
	New(Comment, init);
	FileAdmin(fiInvoiceNodes)^.LogOn;
	ItemTree.Init(fiInvoiceNodes);
end;


destructor TGoodsIn.Done;
begin
	ItemTree.Done;

	FileAdmin(fiInvoiceNodes)^.LogOff;
	Dispose(Comment, done);
	inherited Done;
end;


{==== CREATE DISPLAY-LINE-FORMAT STRING ============}
function TGoodsIn.DisplayLine;
begin
 	DisplayLine := RecDate.Digit8+' Goods Received '+Ref;
end;


{**************************************************************************
 ***                                                                    ***
 ***                  GoodsIn EDIT BOX                                    ***
 ***                                                                    ***
 **************************************************************************}
{========= DO EDIT =======================}
procedure TGoodsIn.MakeEditBox;
var
	R: TRect;
	InputNote : PInputNote;
	S : string;
	ItemList : PDirNodeViewer; {need the dir pointer - owner of the owning jimmy}
	ScrollBar : PSCrollBar;
  FromWhoLine : PInputDirectory;


begin
	if not Comment^.Loaded then Comment^.LoadText;
  if not ItemTree.Loaded then ItemTree.LoadTree;

	R.Assign(0, 0, 65,19);
	EditBox := New(PEditBox, init(R, 'Goods Received',Caller));

	inherited MakeEditBox(EditBox, Caller);

	{Add input fields}
	with EditBox^ do begin

		InsTitledField(10,  1, 10, 1, 'Received', New(PInputDate, init(R)));

		InsTitledField(30,  1, 5, 1, '~R~ef', New(PINputRefNum, init(R, 5, srGoodsIn)));

		InsTitledField(10,  2, 38, 1,'~F~rom', New(PInputDirectory, init(R, 38, fiFullDirIdx)));
    FromWhoLine := PInputDirectory(Current);

		{---- Item List ---}
		R.Assign(1,  4, Size.X-2, 13);
		New(ItemList, init(R, 0, GoodsInNewMenu, FromWhoLine));
		InsLabel(11,  R.A.Y-1, 'Item ~L~ist', ItemList);
		Insert(ItemList^.VSCrollBar);   	{Scroll bar}
		Insert(ItemList);{}
		PInputDirectory(FromWhoLine)^.SetTargetLink(ItemList);

		{--- Comment box ---}
		R.Assign(7, 14, 38, 17);
		New(InputNote, Init(R, 200, 0, nil, EditBox));
		Insert(InputNote);
		InsLabel(7, 14, '~N~otes', InputNote);
		Current^.GrowMode := 0;

		{-- Buttons --}
		Insert(New(PJimmyOKButton, Init(39,16, @Self)));
		InsCancelButton(49, 16);

  	EndInit;

    if (Ref <>'') and (FromWho<>-1) then ItemList^.Focus; {move focus straight to list}
	end;

end;


{*****************************************
 ***     STREAMING DEFINITIONS         ***
 *****************************************}

constructor TGoodsIn.Load(var S : TStream);
var Ver : byte;

begin
	CommonInit;

	{--- Load fields -----}
	S.Read(Ver, 1);

	case ver of
		1 : begin
			S.Read(Ref, sizeof(Ref));
			S.Read(FromWho, 4);

			ItemTree.Load(S);

	    RecDate.Load(S);

			Comment^.Load(S);

      S.Read(StockUpdated, 1);
	end;
	else
		DBaseError(nil,'Unrecognised GoodsIn Version '+B2Str(Ver),'');
	end;

end;



procedure TGoodsIn.Store(var S : TStream);
var
	StartPos : longint;
	ver : byte;

begin
	StartPos := S.GetPos;
	Ver := 1; S.Write(Ver, 1);

	S.Write(Ref, sizeof(Ref));
	S.Write(FromWho, 4);

	ItemTree.Store(S);

	RecDate.Store(S);

	Comment^.Store(S);

  S.Write(StockUpdated, 1);

	TopUpRecord(S, TGoodsInSize, StartPos);
end;

function TGoodsIn.GetKey;
begin
	if RecDate.Blank then
		GetKey := 0                 {Make sure appears at beginning}
	else
		GetKey := 65535-RecDate.Days;  {Reverse Sort on GoodsIn date}
end;

procedure TGoodsIn.StoreSelf;
begin
	if not StockUpdated and (ConfirmMessage('     Update Stock?     ','')=cmYes) then UpdateStock;
	StoreJimmy(@Self);
 	HookJimmyToID(@Self, FromWho, hkHistory, srGoodsIn);
end;


{*************************************************
 ***  SET CODES (FOR PRINT)                    ***
 *************************************************}
{=========== SET CODES ==========}
procedure TGoodsIn.SetFormCodes;
begin
	Output^.ClearCodes;

	Output^.SetCode('RTITLE','Goods Received');

	Output^.SetCodedFunc('ITEMS',PrintInvoiceTree, @ItemTree);
{  SetInvoiceItemsCode(ItemTree, Output);{}

	Output^.SetCode('DT', RecDate.Digit10);        {GoodsIn date, not today}
	Output^.SetCode('REF', Ref+' ');

	{Comment block}
	if not Comment^.Loaded then Comment^.LoadText;
	Output^.SetCode('NOTES',Comment^.Extract(1,256));  {maximum amount extractable}

	{DirectoryItem stuff}
  SetJimmyIDFormCodes(FromWho, Output, 'FROM');
end;


{**************************************
 ***         PRINT GoodsIn           ***
 **************************************}
function TGoodsIn.Print;
var Control : word;
begin
	Print := cmCancel;

	ThinkingOn('Printing');
	if (prType and pmScope)= prFullBlck then begin
		{--- Print summary for history print}
		Output^.Writeln(DisplayLine(0,0));
	end else begin
    {print full report - for checking with perhaps?}
		if not Comment^.Loaded then Comment^.LoadText;
    if not ItemTree.Loaded then ItemTree.LoadTree;

		{---- Print header ----}
		{Set up codes}
		SetFormCodes(Output,'');
		control := Output^.StartPrint('','GOODSIN');

		{Standard Form}
		if not Output^.FormFound then DBAseWarning('No Goods Received form','Create GOODSIN.HDR etc in Maintenance');

		{printing items now done in form}

		{GoodsIn Footer}
		SetFormCodes(Output,''); {overwrite any VTOT's etc that GoodsIn items have set}
		Control := Output^.EndPrint;
  end;

	ThinkingOff;
end;

	{Stock control on a tree}
	procedure DoNode(Node : PNodeItem); far;
  var Product : PProduct;
  		I : integer;
  begin
		if typeof(Node^)=typeof(TProductInvNode) then begin
			Product := PProduct(JimmyStream^.GetAt(PProductInvNode(Node)^.ProductID));

      I := Product^.GetArrayPosOfUnit(PProductInvNode(Node)^.Units);

      if I>-1 then begin
      	Product^.NumInstock[I] := Product^.Numinstock[I] + S2Lint(PProductInvNode(Node)^.Quantity);

        {allow for purchase ordering may not be being used - daft if not...}
        if Product^.OnOrder[I]>0 then Product^.OnOrder[I] := Product^.OnOrder[I] - S2Lint(PProductInvNode(Node)^.Quantity);

      	JimmyStream^.PutAt(PProductInvNode(Node)^.ProductID, Product);
      end;

			dispose(Product, done);
		end;
  end;

procedure TGoodsIn.UpdateStock;

begin
  StockUpdated := True;

  {run through items doing stock control bit}
  if not ItemTree.Loaded then ItemTree.LoadTree;

  FileAdmin(fiJimmys)^.LogOn;
  ItemTree.ForEach(DoNode);
  FileAdmin(fiJimmys)^.LogOff;{}
end;

procedure InsertGoodsIn;
var GoodsIn : PGoodsIn;
begin
	New(GoodsIn, init(nil));
  GoodsIn^.Edit(Desktop);
  dispose(GoodsIn, done);
end;



{**************************************
 ***       INITIALISER              ***
 **************************************}

begin
{$IFDEF kstock}
	{Register existence in history list  - used by chain viewers}
	RegisterHistoryItem('~G~oods Received',cmNewGoodsIn, CreateGoodsIn);
	RegisterType(RGoodsIn);

  {Register Product Invoice item}
	AddItemEnd(GoodsInNewMenu, NewItem('~P~roduct Item', '', kbNone, cmNewProductInvNode, hcNoContext,	nil));
{	RegisterCreator(cmNewProductInvNode, CreateProductInvNode);{done in kinvnode}
{$ENDIF}

	{Register one-off GoodsIns with desktop}
	AppMenuBar^.Add2EndMenu('~N~ew',
	 	NewItem('~G~oods Received', '', kbNone, cmNewDesktopGoodsIn, hcNoContext,
	nil));
	RegisterTask(DesktopTasks, cmNewDesktopGoodsIn, InsertGoodsIn);
{}
end.
