INVOICE.MOD 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328
  1. IMPLEMENTATION MODULE Invoice;
  2. (*
  3. * ModBase
  4. * Release 3.0
  5. * (c) Copyright 1986 - 1991 PMI
  6. * P.O. Box 8402
  7. * Green Bay Wi 53308
  8. * All Rights Reserved
  9. * by Ed Ross
  10. *)
  11. FROM ModBase3 IMPORT UpdateDBFile,WriteDBRec,DeleteRecord,ReadDBRec,
  12. AppendBlank,Record;
  13. FROM Gas IMPORT CheckOutGas,CheckInGas,GasAmountDue,DeleteGasFromInv;
  14. FROM PMIGlobals IMPORT PMIScreens,Today,TodayStr,TodayDays,Config,
  15. OpenReportDevice,CloseReportDevice,NormalTitle;
  16. FROM PriceTable IMPORT ClearGrpCnt,AddGrp,GrpTotal,GetPrice,
  17. GetPriceTable;
  18. FROM DateFunctions IMPORT DateToStr,Date,DaysSince1900;
  19. FROM PosUtils IMPORT Equal,Pos;
  20. FROM StrEdit IMPORT CrunchBlanks,DeleteRightJustified,Append,
  21. CAPstr,OverWrite,RightJustify,Center;
  22. FROM StrConv IMPORT CardinalToStr,RealToStr,StrToReal;
  23. FROM M2Strings IMPORT Length,CompareStr,Assign;
  24. FROM LowLevel IMPORT Fill;
  25. FROM DBStuff IMPORT MakeSeqNbr,FindAll,ReadAllRecs,MakeKey,
  26. ConditionType,ChangeDateField,DeleteAllRecs;
  27. FROM DBUtils IMPORT ReadCardField,ReadRealField,ReadDateField,
  28. ChangeCardField,ChangeRealField,PrintFrame;
  29. FROM NumTypes IMPORT Real8;
  30. FROM Payments IMPORT MakePayment;
  31. FROM DBFPayments IMPORT OpenPaymentsDBF,ClosePaymentsDBF;
  32. FROM Customer IMPORT GetCustNbr,GetCustTerms,GetCustSalesRep,GetCustShipVia,
  33. GetCustDisAmount,GetCustDisCntLvl,GetCustTaxable,SetCustOutStd,
  34. GetCustFreeFrght,AddressRec,AddressTypes,GetCustAddr,GetCurrCustName,
  35. SetCustLastInvDate,AddCustYTD,AddCustOutStd;
  36. FROM StringIO IMPORT PrintMessage,ErrorMessage,WriteEol,WriteStr;
  37. (* these next two are from stonybrook - the pmi version doesn't work*)
  38. FROM SmartScreen IMPORT ClearScreen;
  39. FROM VWindows IMPORT ClearPart, CurrentWindow, SetCursorHeight;
  40. FROM ScrnUtl2 IMPORT CloseDisplayFrame;
  41. FROM ScrnUtl1 IMPORT GetFieldRec,PutFieldRec,FieldNum,FieldListTotal;
  42. FROM ScrnTypes IMPORT DisplayFrame,InitDisplayFrame,AFrameName,
  43. DispCode,ContinueInput,CancelInput,SubmitInput,InputFieldRecord;
  44. FROM FramePainter IMPORT ShowDisplayFrame,RedrawField,RedrawArea;
  45. FROM InputManager IMPORT ControlFrame;
  46. FROM FrameManager IMPORT EraseFrame;
  47. FROM Prompts IMPORT Prompt,PromptStr,PromptYN;
  48. FROM SYSTEM IMPORT ADR,SIZE,TSIZE,ADDRESS;
  49. FROM ControlUtils IMPORT ControlSeparately, LoadFrameList,Control,ReadInput,
  50. ChangeField,AddMenuItem,AddStrField;
  51. FROM DspFiles IMPORT OpenDisplayFile,ReadDisplayFrame;
  52. FROM HandleIO IMPORT FileExists,OpenFile,CloseHandle;
  53. FROM GenLists IMPORT GenList, NewList,ListLength,GetElmt,ElmtNow,GetElmtAdr,
  54. JoinLists,ListDelete,ListInsert,DisposeList,ShellSortList,SortList,NilList;
  55. FROM Invtry IMPORT UpdateInvQuant,GeneralInventory;
  56. FROM DBFInvtry IMPORT InvtryRec,MoveInvtryToDBF,MoveInvtryFromDBF,
  57. FindInvtryByInvcode,NextInvtry,PrevInvtry,LastInvtry,InvtryDBF,
  58. InvcodeIdx;
  59. FROM DBFOrder IMPORT OrderRec,MoveOrderToDBF,MoveOrderFromDBF,OrderDBF,
  60. InvnbrIdx,OpenOrderDBF,CloseOrderDBF;
  61. FROM Invtry IMPORT GetInvItem;
  62. FROM UOpsExt IMPORT Lookup,LookupProc;
  63. FROM UserOps IMPORT AKeyHandler,TheKeyHandler;
  64. IMPORT Key;
  65. FROM VStorage IMPORT DosAlloc,DosDealloc;
  66. FROM InvoicePrint IMPORT PrintInvoice,PostSales;
  67. FROM DBFInvoice IMPORT InvoiceDBF, OpenInvoiceDBF,InvoiceIdx,
  68. CloseInvoiceDBF,InvoiceRec,FindInvoiceByInvoice,CustidIdx,
  69. FindInvoiceByCustid,NextInvoice,PrevInvoice,InvoiceDBF,
  70. FirstInvoice,LastInvoice,MoveInvoiceToDBF,MoveInvoiceFromDBF;
  71. (***********************************************************************
  72. invoices are stored with the invoice number indexed and the
  73. customer number indexed.
  74. The customer number is indexed as
  75. Customer Number + Status
  76. Where status =
  77. 'O' - Open - not yet printed so can be edited
  78. 'P' - Posted (printed ) - can not be editied but can be viewes
  79. 'C' - Invoice is closed i.e. paid off
  80. Item Status = 'R' - Items still recorded
  81. 'D' - Items deleted
  82. ********************************************************************)
  83. VAR
  84. Status : INTEGER;
  85. J : CARDINAL;
  86. NextFrame,EndingFrame : AFrameName;
  87. SelChar : CHAR;
  88. PullDnMenu : GenList;
  89. ItemsChanged : BOOLEAN;
  90. PROCEDURE SortItemList(Item1 : ADDRESS; Size1 : CARDINAL;
  91. Item2 : ADDRESS; Size2 : CARDINAL) : INTEGER;
  92. VAR
  93. I1,I2 : POINTER TO InvoiceItem;
  94. BEGIN
  95. I1 := Item1;
  96. I2 := Item2;
  97. RETURN CompareStr(I1^.ItemOrderRec.ITEMNBR,I2^.ItemOrderRec.ITEMNBR);
  98. END SortItemList;
  99. PROCEDURE UpdateOrderScreen();
  100. (* redraw just the fields on the screen rather than the entire screen*)
  101. VAR
  102. J,K : CARDINAL;
  103. BEGIN
  104. K := FieldListTotal(OrderItemDF);
  105. FOR J := 1 TO K DO
  106. RedrawField(OrderItemDF,J,(K=1)); (* make first field active field*)
  107. END;
  108. END UpdateOrderScreen;
  109. PROCEDURE UpdateOrd( );
  110. VAR Str : ARRAY[0..12] OF CHAR;
  111. BEGIN
  112. WITH CurrentItem^.ItemOrderRec DO
  113. ChangeField(OrderItemDF,ITEMNBR,'Item',TRUE);
  114. RealToStr(TOTAL,2,8,Str);
  115. ChangeField(OrderItemDF,Str,'Total',TRUE); (* computed field *)
  116. ChangeRealField(OrderItemDF,QNTSOLD,'Quant');
  117. ChangeField(OrderItemDF,UNITS,'Units',TRUE); (* alow override *)
  118. ChangeField(OrderItemDF,DESC,'Desc',TRUE);
  119. ChangeField(OrderItemDF,NOTES1,'Notes1',TRUE);
  120. ChangeField(OrderItemDF,NOTES2,'Notes2',TRUE);
  121. ChangeField(OrderItemDF,NOTES3,'Notes3',TRUE);
  122. ChangeField(OrderItemDF,MANPRICE,'Override',TRUE);
  123. ChangeRealField(OrderItemDF,UNITPRC,'UnitPrice');
  124. END;
  125. WITH CurrentItem^.InventoryItem DO
  126. ChangeField(OrderItemDF,GROUP,'Group',TRUE);
  127. RealToStr(ONHAND,2,8,Str);
  128. ChangeField(OrderItemDF,Str,'OnHand',TRUE);
  129. CardinalToStr(MINORDER,5,Str);
  130. ChangeField(OrderItemDF,Str,'MinOrder',TRUE);
  131. ChangeCardField(OrderItemDF,PRICETBL,'TableNbr');
  132. END;
  133. WITH CurrentItem^ DO
  134. ChangeCardField(OrderItemDF,Q1,'Q1');
  135. ChangeCardField(OrderItemDF,Q2,'Q2');
  136. ChangeCardField(OrderItemDF,Q3,'Q3');
  137. ChangeCardField(OrderItemDF,Q4,'Q4');
  138. ChangeRealField(OrderItemDF,P1,'P1');
  139. ChangeRealField(OrderItemDF,P2,'P2');
  140. ChangeRealField(OrderItemDF,P3,'P3');
  141. ChangeRealField(OrderItemDF,P4,'P4');
  142. END;
  143. UpdateOrderScreen();
  144. END UpdateOrd;
  145. PROCEDURE LookUpInv(VAR ItmCode : ARRAY OF CHAR);
  146. (* called from userops to lookup an item when the user exists an item
  147. fields
  148. This routine will always store the results in the current item
  149. inventory record *)
  150. VAR
  151. Tmp : ARRAY[0..20] OF CHAR;
  152. PROCEDURE InitOrder();
  153. BEGIN
  154. WITH CurrentItem^ DO
  155. Assign( CurrentInvoice.INVOICE,ItemOrderRec.INVNBR );
  156. Assign( InventoryItem.INVCODE,ItemOrderRec.ITEMNBR);
  157. Assign( InventoryItem.DESC,ItemOrderRec.DESC );
  158. ItemOrderRec.UNITPRC := InventoryItem.UNITPRICE;
  159. Assign(InventoryItem.UNITS,ItemOrderRec.UNITS );
  160. ItemOrderRec.MANPRICE := 'N';
  161. GetPriceTable(InventoryItem.PRICETBL,Q1,Q2,Q3,Q4,P1,P2,P3,P4);
  162. END;
  163. END InitOrder;
  164. BEGIN
  165. CAPstr(ItmCode);
  166. IF CurrentItem^.BeenAdded
  167. THEN
  168. (* IF NOT Special(ItmCode)
  169. THEN
  170. ItmCode := CurrentItem^.ItemOrderRec.INVNBR;
  171. END; *)
  172. RETURN
  173. END;
  174. IF Special(ItmCode)
  175. THEN (* credit or special order *)
  176. Assign( CurrentInvoice.INVOICE,CurrentItem^.ItemOrderRec.INVNBR );
  177. CurrentItem^.ItemOrderRec.MANPRICE := 'Y';
  178. Assign(ItmCode,CurrentItem^.ItemOrderRec.ITEMNBR );
  179. Assign( ItmCode,Tmp);
  180. UpdateOrd();
  181. RETURN
  182. END;
  183. Assign( ItmCode,Tmp);
  184. CrunchBlanks(Tmp);
  185. CrunchBlanks(CurrentItem^.InventoryItem.INVCODE);
  186. IF Equal(Tmp,CurrentItem^.InventoryItem.INVCODE)
  187. THEN
  188. RETURN; (* didn't change the items - so we're ok *)
  189. END;
  190. IF FindInvtryByInvcode(Tmp)
  191. THEN
  192. MoveInvtryFromDBF(CurrentItem^.InventoryItem);
  193. CurrentItem^.InventoryFilePos := Record(InvtryDBF);
  194. InitOrder(); (* re init the display frame *)
  195. ReadDisplayFrame(PMIScreens,OrderItemDF,'OrderItem');
  196. UpdateOrd();
  197. ELSE
  198. GeneralInventory(ItmCode);
  199. MoveInvtryFromDBF(CurrentItem^.InventoryItem);
  200. Assign( CurrentItem^.InventoryItem.INVCODE,ItmCode );
  201. CurrentItem^.InventoryFilePos := Record(InvtryDBF);
  202. InitOrder();
  203. ReadDisplayFrame(PMIScreens,OrderItemDF,'OrderItem');
  204. ShowDisplayFrame(OrderItemDF,0,0,0,0);
  205. RedrawArea(InvoiceHeadDF,1,10,80,13);
  206. UpdateOrd();
  207. END;
  208. END LookUpInv;
  209. PROCEDURE ReadAnInvoice(VAR AddrOfRec : ADDRESS; VAR SizeOfRec: CARDINAL);
  210. (* a procedure passed to reall all recs to read an invoice record *)
  211. VAR
  212. P : POINTER TO FInvoice;
  213. BEGIN
  214. SizeOfRec := SIZE(FInvoice);
  215. DosAlloc(P,SizeOfRec);
  216. MoveInvoiceFromDBF(P^.Invoice);
  217. P^.LI := Record(InvoiceDBF);
  218. AddrOfRec := P;
  219. END ReadAnInvoice;
  220. PROCEDURE Special(Item:ARRAY OF CHAR) : BOOLEAN;
  221. BEGIN
  222. IF (Pos(Credit,Item) = 0) OR (Pos(SpecialOrd,Item) = 0)
  223. THEN RETURN TRUE;
  224. ELSE RETURN FALSE;
  225. END;
  226. END Special;
  227. PROCEDURE ReadScrn();
  228. VAR
  229. Str : ARRAY[0..15] OF CHAR;
  230. B : BOOLEAN;
  231. BEGIN
  232. IF NOT OrderItemDF^.FrameChanged (* just looked - nothing changed *)
  233. THEN
  234. RETURN;
  235. END;
  236. WITH CurrentItem^.ItemOrderRec DO
  237. ReadInput(OrderItemDF,Str,'Quant');
  238. B := StrToReal(Str,0,QNTSOLD);
  239. ReadInput(OrderItemDF,Str,'UnitPrice');
  240. B := StrToReal(Str,0,UNITPRC);
  241. ReadInput(OrderItemDF,DESC,'Desc');
  242. ReadInput(OrderItemDF,UNITS,'Units');
  243. ReadInput(OrderItemDF,MANPRICE,'Override');
  244. CAPstr(MANPRICE);
  245. ReadInput(OrderItemDF,NOTES1,'Notes1');
  246. ReadInput(OrderItemDF,NOTES2,'Notes2');
  247. ReadInput(OrderItemDF,NOTES3,'Notes3');
  248. END;
  249. END ReadScrn;
  250. PROCEDURE ReadHeader();
  251. VAR
  252. C : CARDINAL;
  253. R : Real8;
  254. Str : ARRAY[0..15] OF CHAR;
  255. BEGIN
  256. WITH CurrentInvoice DO
  257. ReadInput(InvoiceHeadDF,CUSTPO,'PONbr');
  258. ReadInput(InvoiceHeadDF,SALESMAN,'SalesRep');
  259. ReadInput(InvoiceHeadDF,TERMS,'Terms');
  260. ReadInput(InvoiceHeadDF,SHIPVIA,'ShipVia');
  261. ReadInput(InvoiceHeadDF,TAXABLE,'Taxable');
  262. ReadDateField(InvoiceHeadDF,INVDATE,'InvDate');
  263. ReadRealField(InvoiceHeadDF,INVDSCNT,'Discount');
  264. ReadCardField(InvoiceHeadDF,DFLTLVL,'DefaultLevel');
  265. ReadRealField(InvoiceHeadDF,SHIPPING,'Shipping');
  266. ReadInput(InvoiceHeadDF,NOTE1,'NOTE1');
  267. ReadInput(InvoiceHeadDF,NOTE2,'NOTE2');
  268. ReadInput(InvoiceHeadDF,NOTE3,'NOTE3');
  269. ReadInput(InvoiceHeadDF,NOTESFOR,'NOTESFOR');
  270. CAPstr(NOTESFOR);
  271. END;
  272. END ReadHeader;
  273. PROCEDURE UpdateInventory();
  274. VAR
  275. Str : ARRAY[0..30] OF CHAR;
  276. StrNum : ARRAY[0..10] OF CHAR;
  277. R : Real8;
  278. BEGIN
  279. WITH CurrentItem^ DO
  280. IF Special(ItemOrderRec.ITEMNBR)
  281. THEN RETURN;
  282. END;
  283. ItemOrderRec.QNTORDER := ItemOrderRec.QNTSOLD;
  284. ReadDBRec(InvtryDBF,InventoryFilePos); (* get uptodate inventory item
  285. and position the file pointer to the item *)
  286. IF ItemOrderRec.QNTORDER > InventoryItem.ONHAND
  287. THEN
  288. ItemOrderRec.QNTSOLD := InventoryItem.ONHAND;
  289. RealToStr(ItemOrderRec.QNTORDER - ItemOrderRec.QNTSOLD,2,5,StrNum);
  290. ItemOrderRec.NOTES1 := 'Short - ';
  291. Append(ItemOrderRec.NOTES1,StrNum);
  292. InventoryItem.ONHAND := 0.0;
  293. IF InventoryItem.STOCKED
  294. THEN Append(ItemOrderRec.NOTES1,' - Please reorder');
  295. ELSE ItemOrderRec.NOTES1 := ' -Item no longer stocked'
  296. END;
  297. Prompt(ItemOrderRec.NOTES1);
  298. ELSE
  299. InventoryItem.ONHAND := InventoryItem.ONHAND - ItemOrderRec.QNTSOLD;
  300. END;
  301. END; (* end of with *)
  302. (* update the inventory record immediately *)
  303. MoveInvtryToDBF(CurrentItem^.InventoryItem);
  304. WriteDBRec(InvtryDBF);
  305. END UpdateInventory;
  306. PROCEDURE AddItems(VAR Inv : InvoiceRec);
  307. VAR
  308. NxtFrame : AFrameName;
  309. OldLookup : Lookup;
  310. J : CARDINAL;
  311. PROCEDURE InsertInList();
  312. BEGIN
  313. IF CurrentItem^.BeenAdded
  314. THEN
  315. RETURN
  316. END;
  317. CurrentItem^.BeenAdded := TRUE;
  318. IF NOT Special(CurrentItem^.ItemOrderRec.ITEMNBR)
  319. THEN
  320. UpdateInventory();
  321. END; (* if not special*)
  322. ListInsert(CurrentItem^,2,OrderItemLst,9999); (* insert at end *)
  323. Recompute();
  324. END InsertInList;
  325. PROCEDURE ShowSummary();
  326. CONST
  327. Title =
  328. 'Item Units Quant Description Price Total';
  329. VAR
  330. Cnt, LL : CARDINAL;
  331. Size,Code : CARDINAL;
  332. Line : ARRAY[0..80] OF CHAR;
  333. Tmp : ARRAY[0..12] OF CHAR;
  334. FieldRec : InputFieldRecord;
  335. (*
  336. 012345678901234567890123456789012345678901234567890123456789012345678901234
  337. 0 1 2 3 4 5 6 7
  338. Item Units Quant Description Price Total
  339. xxxxxx xxxxx xxx.x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxx.xx xxxxx.xx
  340. *)
  341. BEGIN
  342. Recompute();
  343. SortList(OrderItemLst,SortItemList);
  344. InitDisplayFrame(SummaryDF,CurrentWindow);
  345. AddStrField(SummaryDF,2,2,Title,75);
  346. GetFieldRec(SummaryDF,1,FieldRec);
  347. FieldRec.typ := DispCode; (* headline = display code *)
  348. PutFieldRec(FieldRec,SummaryDF,1);
  349. SummaryDF^.headline := 2;
  350. LL := ListLength(OrderItemLst);
  351. FOR Cnt := 1 TO LL DO
  352. GetElmtAdr(OrderItemLst,Cnt,CurrentItem,Size,Code);
  353. Fill(ADR(Line),SIZE(Line),' ');
  354. Line[78] := 0C; (* force end of line *)
  355. WITH CurrentItem^.ItemOrderRec DO
  356. OverWrite(ITEMNBR,Line,0);
  357. OverWrite(UNITS,Line,8);
  358. RealToStr(QNTSOLD,1,5,Tmp);
  359. OverWrite(Tmp,Line,15);
  360. OverWrite(DESC,Line,22);
  361. RealToStr(UNITPRC,2,7,Tmp);
  362. OverWrite(Tmp,Line,58);
  363. RealToStr(TOTAL,2,7,Tmp);
  364. OverWrite(Tmp,Line,67);
  365. AddMenuItem(SummaryDF,2,Cnt+2,Line,78,0,ITEMNBR);
  366. END; (* end of with *)
  367. END; (* end of for *)
  368. ShowDisplayFrame(SummaryDF,1,13,80,24);
  369. END ShowSummary;
  370. PROCEDURE InList(ItemCode : ARRAY OF CHAR) : BOOLEAN;
  371. VAR Tmp : POINTER TO InvoiceItem;
  372. J : CARDINAL;
  373. Code,Size : CARDINAL;
  374. BEGIN
  375. FOR J := 1 TO ListLength(OrderItemLst) DO
  376. GetElmtAdr(OrderItemLst,J,Tmp,Size,Code);
  377. IF Equal(Tmp^.ItemOrderRec.ITEMNBR,ItemCode)
  378. THEN
  379. Prompt('Item already in invoice - can not add');
  380. RETURN TRUE;
  381. END;
  382. END; (* end for j *)
  383. RETURN FALSE;
  384. END InList;
  385. BEGIN (* additems *)
  386. InitDisplayFrame(OrderItemDF,CurrentWindow);
  387. OldLookup := LookupProc;
  388. (* call(reg_param=>()) *)
  389. LookupProc := LookUpInv;
  390. (* call(reg_param=>(ax,bx,cx,dx,st0,st6,st5,st4,st3)) *)
  391. ItemsChanged := TRUE;
  392. REPEAT
  393. DosAlloc(CurrentItem,SIZE(CurrentItem^));
  394. Fill(CurrentItem,SIZE(CurrentItem^),0);
  395. CurrentItem^.BeenAdded := FALSE;
  396. CurrentItem^.GasPriced := FALSE;
  397. ReadDisplayFrame(PMIScreens,OrderItemDF,'OrderItem');
  398. ControlFrame(OrderItemDF,1,'',TRUE,NxtFrame);
  399. ReadScrn();
  400. IF CurrentItem^.ItemOrderRec.ITEMNBR[0] > 0C (* F10 pressed not data*)
  401. THEN (* the f10 key pressed - data on the screen *)
  402. IF NOT InList(CurrentItem^.ItemOrderRec.ITEMNBR)
  403. THEN
  404. InsertInList();
  405. ELSE
  406. DosDealloc(CurrentItem,SIZE(CurrentItem^));
  407. END;
  408. ELSE (* f10 or Esc key pressed - not data on screen *)
  409. IF NOT CurrentItem^.BeenAdded (* if blank screen - done*)
  410. THEN
  411. NxtFrame := ''; (* blank screen - exit time*)
  412. DosDealloc(CurrentItem,SIZE(CurrentItem^));
  413. END;
  414. END;
  415. UNTIL NOT Equal(OrderItemDF^.normlnext,NxtFrame);
  416. LookupProc := OldLookup;
  417. CloseDisplayFrame(OrderItemDF);
  418. ShowSummary();
  419. END AddItems;
  420. PROCEDURE ShowSummary();
  421. CONST
  422. Title =
  423. 'Item Units Quant Description Price Total';
  424. VAR
  425. Cnt, LL : CARDINAL;
  426. Size,Code : CARDINAL;
  427. Line : ARRAY[0..80] OF CHAR;
  428. Tmp : ARRAY[0..12] OF CHAR;
  429. FieldRec : InputFieldRecord;
  430. (*
  431. 012345678901234567890123456789012345678901234567890123456789012345678901234
  432. 0 1 2 3 4 5 6 7
  433. Item Units Quant Description Price Total
  434. xxxxxx xxxxx xxx.x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxx.xx xxxxx.xx
  435. *)
  436. BEGIN
  437. Recompute();
  438. SortList(OrderItemLst,SortItemList);
  439. InitDisplayFrame(SummaryDF,CurrentWindow);
  440. AddStrField(SummaryDF,2,2,Title,75);
  441. GetFieldRec(SummaryDF,1,FieldRec);
  442. FieldRec.typ := DispCode; (* headline = display code *)
  443. PutFieldRec(FieldRec,SummaryDF,1);
  444. SummaryDF^.headline := 2;
  445. LL := ListLength(OrderItemLst);
  446. FOR Cnt := 1 TO LL DO
  447. GetElmtAdr(OrderItemLst,Cnt,CurrentItem,Size,Code);
  448. Fill(ADR(Line),SIZE(Line),' ');
  449. Line[78] := 0C; (* force end of line *)
  450. WITH CurrentItem^.ItemOrderRec DO
  451. OverWrite(ITEMNBR,Line,0);
  452. OverWrite(UNITS,Line,8);
  453. RealToStr(QNTSOLD,1,5,Tmp);
  454. OverWrite(Tmp,Line,15);
  455. OverWrite(DESC,Line,22);
  456. RealToStr(UNITPRC,2,7,Tmp);
  457. OverWrite(Tmp,Line,58);
  458. RealToStr(TOTAL,2,7,Tmp);
  459. OverWrite(Tmp,Line,67);
  460. AddMenuItem(SummaryDF,2,Cnt+2,Line,78,0,ITEMNBR);
  461. END; (* end of with *)
  462. END; (* end of for *)
  463. ShowDisplayFrame(SummaryDF,1,13,80,24);
  464. END ShowSummary;
  465. PROCEDURE SelectFromSummary();
  466. (* select an item from the list and put into current item *)
  467. VAR
  468. NextFrame : AFrameName;
  469. K : CARDINAL;
  470. Size,Code : CARDINAL;
  471. BEGIN
  472. ControlFrame(SummaryDF,1,'',FALSE,NextFrame);
  473. (* CrunchBlanks(NextFrame); *)
  474. K := 1;
  475. LOOP
  476. IF K > ListLength(OrderItemLst)
  477. THEN EXIT;
  478. END;
  479. GetElmtAdr(OrderItemLst,K,CurrentItem,Size,Code);
  480. IF Equal(NextFrame,CurrentItem^.ItemOrderRec.ITEMNBR)
  481. THEN EXIT;
  482. END;
  483. INC(K);
  484. END; (* end of loop *)
  485. CloseDisplayFrame(SummaryDF);
  486. END SelectFromSummary;
  487. PROCEDURE Recompute();
  488. (* go through the list twice
  489. 1 - count the items in each group
  490. 2 - get price based on group *)
  491. VAR
  492. Total : Real8;
  493. LL : CARDINAL;
  494. J : CARDINAL;
  495. Code,Size : CARDINAL;
  496. PROCEDURE CreditCompute(VAR ItemOrderRec :OrderRec) : Real8;
  497. BEGIN
  498. IF ItemOrderRec.UNITPRC > 0.0 (* credit items are negative *)
  499. THEN ItemOrderRec.UNITPRC := - ItemOrderRec.UNITPRC;
  500. END;
  501. ItemOrderRec.TOTAL := ItemOrderRec.UNITPRC;
  502. RETURN ItemOrderRec.TOTAL;
  503. END CreditCompute;
  504. PROCEDURE GasCompute(VAR ItemOrderRec : OrderRec; VAR GasPriced : BOOLEAN) : Real8;
  505. BEGIN
  506. IF ItemOrderRec.MANPRICE = 'Y'
  507. THEN RETURN ItemOrderRec.TOTAL; (* already priced - *)
  508. END;
  509. ItemOrderRec.MANPRICE := 'Y';
  510. GasAmountDue(CurrentInvoice.CUSTID,
  511. ItemOrderRec.ITEMNBR,
  512. TRUNC(ItemOrderRec.QNTSOLD),
  513. CurrentInvoice.INVDATE,
  514. ItemOrderRec.TOTAL,
  515. ItemOrderRec.NOTES1);
  516. RETURN ItemOrderRec.TOTAL;
  517. END GasCompute;
  518. PROCEDURE ComputeNormal() : Real8;
  519. BEGIN
  520. WITH CurrentItem^ DO
  521. IF (InventoryItem.PRICETBL > 0) AND
  522. (ItemOrderRec.MANPRICE = 'N')
  523. THEN
  524. IF InventoryItem.GROUP[0] > 0C (* a group exists *)
  525. THEN
  526. ItemOrderRec.UNITPRC := GetPrice(InventoryItem.PRICETBL,
  527. GrpTotal(InventoryItem.GROUP),
  528. CurrentInvoice.DFLTLVL);
  529. ELSE (* price based on this item alone *)
  530. (* use the qntorder for computing the unit price*)
  531. ItemOrderRec.UNITPRC := GetPrice(InventoryItem.PRICETBL,
  532. TRUNC(ItemOrderRec.QNTORDER),
  533. CurrentInvoice.DFLTLVL);
  534. END; (* not table priced - *)
  535. END;
  536. ItemOrderRec.TOTAL := ItemOrderRec.QNTSOLD * ItemOrderRec.UNITPRC;
  537. END; (* end with *)
  538. RETURN CurrentItem^.ItemOrderRec.TOTAL;
  539. END ComputeNormal;
  540. BEGIN
  541. ClearGrpCnt();
  542. HeaderChanged := TRUE;
  543. LL := ListLength(OrderItemLst); (* go through the list and add items *)
  544. FOR J := 1 TO LL DO
  545. GetElmtAdr(OrderItemLst,J,CurrentItem,Size,Code);
  546. IF CurrentItem^.InventoryItem.GROUP[0] > 0C (*a group exists *)
  547. THEN
  548. AddGrp(CurrentItem^.InventoryItem.GROUP,TRUNC(CurrentItem^.ItemOrderRec.QNTSOLD));
  549. END;
  550. CurrentInvoice.INVNET := 0.0;
  551. END;
  552. FOR J := 1 TO LL DO (* now compute price *)
  553. GetElmtAdr(OrderItemLst,J,CurrentItem,Size,Code);
  554. WITH CurrentItem^ DO
  555. IF Pos(Credit,ItemOrderRec.ITEMNBR) = 0 (* credit item *)
  556. THEN
  557. CurrentInvoice.INVNET := CurrentInvoice.INVNET +
  558. CreditCompute(ItemOrderRec);
  559. ELSIF Pos(GasIn,CurrentItem^.ItemOrderRec.ITEMNBR) = 0
  560. THEN
  561. CurrentInvoice.INVNET := CurrentInvoice.INVNET +
  562. GasCompute(ItemOrderRec,GasPriced);
  563. ELSE
  564. CurrentInvoice.INVNET := CurrentInvoice.INVNET +
  565. ComputeNormal();
  566. END;
  567. END; (* end with current item *)
  568. END; (* end for j *)
  569. CurrentInvoice.INVNET := CurrentInvoice.INVNET * (1.0 - CurrentInvoice.INVDSCNT/100.0);
  570. CAPstr(CurrentInvoice.TAXABLE);
  571. IF (CurrentInvoice.TAXABLE = 'Y')
  572. THEN
  573. CurrentInvoice.INVTAX := CurrentInvoice.INVNET * (Config.TaxRate/100.0); (* add tax *)
  574. ELSE
  575. CurrentInvoice.INVTAX := 0.0;
  576. END;
  577. CurrentInvoice.TOTALAMT := CurrentInvoice.INVNET + CurrentInvoice.INVTAX +
  578. CurrentInvoice.SHIPPING;
  579. ChangeRealField(InvoiceHeadDF,CurrentInvoice.TOTALAMT,'Total'); (*update header screen*)
  580. ChangeRealField(InvoiceHeadDF,CurrentInvoice.INVTAX,'Tax');
  581. ChangeRealField(InvoiceHeadDF,CurrentInvoice.INVNET,'Net');
  582. RedrawField(InvoiceHeadDF,FieldNum(InvoiceHeadDF,'Tax'),FALSE);
  583. RedrawField(InvoiceHeadDF,FieldNum(InvoiceHeadDF,'Net'),FALSE);
  584. RedrawField(InvoiceHeadDF,FieldNum(InvoiceHeadDF,'Total'),FALSE);
  585. END Recompute;
  586. PROCEDURE UpdateInvHeader();
  587. (* update the invoice header and display *)
  588. BEGIN
  589. WITH CurrentInvoice DO
  590. CrunchBlanks(INVOICE);
  591. ChangeField(InvoiceHeadDF,INVOICE,'InvNbr',TRUE);
  592. ChangeDateField(InvoiceHeadDF,INVDATE,'InvDate');
  593. ChangeField(InvoiceHeadDF,SALESMAN,'SalesRep',TRUE);
  594. ChangeField(InvoiceHeadDF,TERMS,'Terms',TRUE);
  595. ChangeField(InvoiceHeadDF,SHIPVIA,'ShipVia',TRUE);
  596. ChangeField(InvoiceHeadDF,TAXABLE,'Taxable',TRUE);
  597. ChangeRealField(InvoiceHeadDF,INVDSCNT,'Discount');
  598. ChangeRealField(InvoiceHeadDF,INVTAX,'Tax');
  599. ChangeRealField(InvoiceHeadDF,INVNET,'Net');
  600. ChangeRealField(InvoiceHeadDF,SHIPPING,'Shipping');
  601. ChangeCardField(InvoiceHeadDF,DFLTLVL,'DefaultLevel');
  602. ChangeRealField(InvoiceHeadDF,TOTALAMT,'Total');
  603. ChangeField(InvoiceHeadDF,NOTE1,'NOTE1',TRUE);
  604. ChangeField(InvoiceHeadDF,NOTE2,'NOTE2',TRUE);
  605. ChangeField(InvoiceHeadDF,NOTE3,'NOTE3',TRUE);
  606. ChangeField(InvoiceHeadDF,NOTESFOR,'NOTESFOR',TRUE);
  607. END;
  608. ShowDisplayFrame(InvoiceHeadDF,0,0,0,0);
  609. END UpdateInvHeader;
  610. PROCEDURE GetInvoice(InvNbr : ARRAY OF CHAR);
  611. (* get the invoice header, get the invoice items, get the inventory items*)
  612. VAR
  613. Items : GenList;
  614. LI : LONGINT;
  615. J : CARDINAL;
  616. Code : CARDINAL;
  617. Tmp : InvoiceItem;
  618. BEGIN
  619. NewList(Items); (* get all items *)
  620. FindAll(InvnbrIdx,InvNbr,EQ,Items);
  621. FOR J := 1 TO ListLength(Items) DO
  622. GetElmt(Items,J,LI,Code);
  623. ReadDBRec(OrderDBF,LI); (* read the record *)
  624. MoveOrderFromDBF(Tmp.ItemOrderRec);
  625. IF NOT Special(Tmp.ItemOrderRec.ITEMNBR)
  626. THEN
  627. IF NOT FindInvtryByInvcode(Tmp.ItemOrderRec.ITEMNBR)
  628. THEN Prompt(' could not find inventory');
  629. ELSE
  630. MoveInvtryFromDBF(Tmp.InventoryItem);
  631. Tmp.InventoryFilePos := Record(InvtryDBF);
  632. END;
  633. ELSE Fill(ADR(Tmp.InventoryItem ),SIZE(Tmp.InventoryItem),0);
  634. END;
  635. Tmp.OldQuant := Tmp.ItemOrderRec.QNTSOLD;
  636. Tmp.BeenAdded := TRUE;
  637. Tmp.GasPriced := TRUE;
  638. GetPriceTable(Tmp.InventoryItem.PRICETBL,Tmp.Q1,Tmp.Q2,Tmp.Q3,Tmp.Q4,
  639. Tmp.P1,Tmp.P2,Tmp.P3,Tmp.P4);
  640. ListInsert(Tmp,1,OrderItemLst,1);
  641. END; (* end for j *)
  642. ShellSortList(OrderItemLst,SortItemList);
  643. END GetInvoice;
  644. PROCEDURE MakeInvoicePrintLine(InvAddr : ADDRESS; VAR Line : ARRAY OF CHAR);
  645. VAR
  646. TmpInv : POINTER TO FInvoice;
  647. B : BOOLEAN;
  648. Str : ARRAY[0..10] OF CHAR;
  649. BEGIN
  650. TmpInv := InvAddr;
  651. Fill(ADR(Line),70,' ');
  652. Line[60] := 0C;
  653. OverWrite(TmpInv^.Invoice.INVOICE,Line,0);
  654. DateToStr(TmpInv^.Invoice.INVDATE,Str,B);
  655. OverWrite(Str,Line,10);
  656. RealToStr(TmpInv^.Invoice.TOTALAMT,2,9,Str);
  657. OverWrite(Str,Line,20);
  658. RealToStr(TmpInv^.Invoice.AMTOUT,2,9,Str);
  659. OverWrite(Str,Line,33);
  660. OverWrite(TmpInv^.Invoice.INVPRNT,Line,53);
  661. END MakeInvoicePrintLine;
  662. PROCEDURE DisplayInvList(TheList : GenList);
  663. VAR
  664. Code,Size: CARDINAL;
  665. K : CARDINAL;
  666. TmpInv : POINTER TO FInvoice;
  667. Line : ARRAY[0..80] OF CHAR;
  668. CustID : ARRAY[0..15] OF CHAR;
  669. B : BOOLEAN;
  670. Str : ARRAY[0..10] OF CHAR;
  671. found : BOOLEAN;
  672. FieldRec : InputFieldRecord;
  673. BEGIN
  674. (*
  675. 1 2 3 4 5
  676. 012345678901234567890123456789012345678901234567890123456
  677. Inv Nbr Inv Date Inv Total Amount Out Status
  678. *)
  679. InitDisplayFrame(SummaryDF,CurrentWindow);
  680. AddStrField(SummaryDF,2,2,
  681. 'Inv Nbr Inv Date Inv Total Amount Outstanding Status',60);
  682. GetFieldRec(SummaryDF,1,FieldRec);
  683. FieldRec.typ := DispCode; (* headline = display code *)
  684. PutFieldRec(FieldRec,SummaryDF,1);
  685. SummaryDF^.headline := 2;
  686. K := ListLength(TheList); (*debug trap *)
  687. FOR J := 1 TO K DO
  688. GetElmtAdr(TheList,J,TmpInv,Size,Code);
  689. MakeInvoicePrintLine(TmpInv,Line);
  690. AddMenuItem(SummaryDF,2,J+2,Line,60,0,TmpInv^.Invoice.INVOICE);
  691. END; (* end of for *)
  692. ShowDisplayFrame(SummaryDF,1,13,80,24);
  693. END DisplayInvList;
  694. PROCEDURE SelectInvoiceFromList(VAR TheList : GenList; ReadInvtry : BOOLEAN);
  695. (* returns the selected invoice in current invoice *)
  696. (* assumes summary df already set up *)
  697. VAR NextFrame : AFrameName;
  698. Size,Code : CARDINAL;
  699. found : BOOLEAN;
  700. K : CARDINAL;
  701. TmpInv : POINTER TO FInvoice;
  702. BEGIN
  703. ControlFrame(SummaryDF,1,'',TRUE,NextFrame);
  704. K := 1;
  705. found := TRUE;
  706. CrunchBlanks(NextFrame);
  707. LOOP
  708. IF K > ListLength(TheList)
  709. THEN
  710. (* Prompt('Could not find invoice '); *)
  711. found := FALSE;
  712. EXIT;
  713. END;
  714. GetElmtAdr(TheList,K,TmpInv,Size,Code);
  715. CrunchBlanks(TmpInv^.Invoice.INVOICE);
  716. IF Equal(TmpInv^.Invoice.INVOICE,NextFrame)
  717. THEN EXIT;
  718. END;
  719. INC(K);
  720. END; (* end of loop *)
  721. CloseDisplayFrame(SummaryDF);
  722. IF found
  723. THEN
  724. ReadDBRec(InvoiceDBF,TmpInv^.LI); (* read the selected item *)
  725. CurrentInvoice := TmpInv^.Invoice; (* make current invoice *)
  726. IF CurrentInvoice.INVPRNT = 'P'
  727. THEN
  728. CurrInvOldAmt := CurrentInvoice.INVNET; (* if they reprint *)
  729. ELSE
  730. CurrInvOldAmt := 0.0; (* keep the ytd amount correct*)
  731. END;
  732. IF ReadInvtry (* if this call from select invoice to update*)
  733. THEN
  734. UpdateInvHeader();
  735. GetInvoice(CurrentInvoice.INVOICE);
  736. ShowSummary();
  737. END;
  738. ELSE
  739. CurrentInvoice.INVOICE := '';
  740. END;
  741. END SelectInvoiceFromList;
  742. PROCEDURE SelectInvoice( );
  743. (* this routine will select from the set of invoices owned by a customer
  744. and return the invoice number of the selected - If esc is hit then no
  745. invoice is selected *)
  746. VAR
  747. SelList : GenList;
  748. PrnList : GenList;
  749. J,K : CARDINAL;
  750. Code,Size: CARDINAL;
  751. TmpInv : POINTER TO FInvoice;
  752. CustID : ARRAY[0..15] OF CHAR;
  753. B : BOOLEAN;
  754. found : BOOLEAN;
  755. BEGIN
  756. GetCustNbr(CustID); (* get the open invoice *)
  757. Append(CustID,'O'); (* only get the open ones *)
  758. MakeKey(CustID);
  759. NilList(SelList);
  760. FindAll(CustidIdx,CustID,EQ,SelList);
  761. ReadAllRecs(InvoiceDBF,ReadAnInvoice,SelList);
  762. GetCustNbr(CustID); (* get all of the printed ones *)
  763. Append(CustID,'P');
  764. MakeKey(CustID);
  765. NilList(PrnList);
  766. FindAll(CustidIdx,CustID,EQ,PrnList);
  767. ReadAllRecs(InvoiceDBF,ReadAnInvoice,PrnList);
  768. JoinLists(PrnList,SelList,1); (* join the two lists - all outstanding*)
  769. IF ListLength(SelList) = 0
  770. THEN Prompt('No open invoices');
  771. CurrentInvoice.INVOICE := '';
  772. DisposeList(SelList);
  773. RETURN;
  774. END;
  775. DisplayInvList(SelList);
  776. SelectInvoiceFromList(SelList,TRUE);
  777. DisposeList(SelList);
  778. END SelectInvoice;
  779. PROCEDURE InvoiceHistory();
  780. VAR
  781. PrnList : GenList;
  782. CustID : ARRAY[0..15] OF CHAR;
  783. B : BOOLEAN;
  784. J : CARDINAL;
  785. Code,Size : CARDINAL;
  786. TotalDue : Real8;
  787. P :POINTER TO FInvoice;
  788. Title1 : ARRAY[0..80] OF CHAR;
  789. Handle : CARDINAL;
  790. BEGIN
  791. OpenInvoiceDBF(TRUE);
  792. GetCustNbr(CustID); (* get all of the printed ones *)
  793. NilList(PrnList);
  794. FindAll(CustidIdx,CustID,BeginsWith,PrnList);
  795. ReadAllRecs(InvoiceDBF,ReadAnInvoice,PrnList);
  796. IF ListLength(PrnList) = 0
  797. THEN Prompt('No invoice History');
  798. DisposeList(PrnList);
  799. RETURN;
  800. END;
  801. DisplayInvList(PrnList);
  802. Control(SummaryDF);
  803. IF PromptYN(' Print the report ',SummaryDF)
  804. THEN
  805. GetCurrCustName(Title1);
  806. Append(Title1,' - Invoice History ');
  807. Handle := OpenReportDevice();
  808. NormalTitle(Title1);
  809. PrintFrame(SummaryDF,Handle);
  810. CloseReportDevice(Handle);
  811. END;
  812. DisposeList(PrnList);
  813. CloseInvoiceDBF();
  814. END InvoiceHistory;
  815. PROCEDURE DeleteInvItems(InvNbr : ARRAY OF CHAR);
  816. VAR TheList : GenList;
  817. BEGIN
  818. CrunchBlanks(InvNbr);
  819. NilList(TheList);
  820. FindAll(InvnbrIdx,InvNbr,EQ,TheList); (* get old invoices *)
  821. IF ListLength(TheList) > 0 (* some invoice have zero items from conversion*)
  822. THEN
  823. DeleteAllRecs(OrderDBF,TheList);
  824. END;
  825. DisposeList(TheList);
  826. END DeleteInvItems;
  827. PROCEDURE InvoiceDaysLate(InvAddr : ADDRESS) : CARDINAL;
  828. (* return the nubmer of days late for an invoice*)
  829. VAR
  830. TodaysDays,
  831. InvoiceDays :CARDINAL;
  832. InvPoint : POINTER TO FInvoice;
  833. BEGIN
  834. InvPoint := InvAddr;
  835. InvoiceDays := DaysSince1900(InvPoint^.Invoice.INVDATE);
  836. RETURN (InvoiceDays - TodaysDays);
  837. END InvoiceDaysLate;
  838. PROCEDURE GetOutstanding(CustID : ARRAY OF CHAR; VAR TheList:GenList);
  839. BEGIN
  840. (* assumes the database is open *)
  841. Append(CustID,'P');
  842. NilList(TheList);
  843. FindAll(CustidIdx,CustID,EQ,TheList);
  844. ReadAllRecs(InvoiceDBF,ReadAnInvoice,TheList);
  845. END GetOutstanding;
  846. PROCEDURE PayInvoice();
  847. VAR
  848. PrnList : GenList;
  849. CustID : ARRAY[0..15] OF CHAR;
  850. PymtDF : DisplayFrame;
  851. ManualPay : BOOLEAN;
  852. FldRec : InputFieldRecord;
  853. PymtAmount : Real8;
  854. Remaining : Real8;
  855. B : BOOLEAN;
  856. CheckNbr : ARRAY[0..10] OF CHAR;
  857. PymtDate : Date;
  858. J : CARDINAL;
  859. Code,Size : CARDINAL;
  860. TotalDue : Real8;
  861. P :POINTER TO FInvoice;
  862. BEGIN
  863. OpenInvoiceDBF(TRUE);
  864. GetCustNbr(CustID); (* get all of the printed ones *)
  865. Append(CustID,'P');
  866. NilList(PrnList);
  867. FindAll(CustidIdx,CustID,EQ,PrnList);
  868. ReadAllRecs(InvoiceDBF,ReadAnInvoice,PrnList);
  869. IF ListLength(PrnList) = 0
  870. THEN Prompt('No outstanding invoices');
  871. DisposeList(PrnList);
  872. RETURN;
  873. END;
  874. TotalDue := 0.0;
  875. FOR J := 1 TO ListLength(PrnList) DO (* zip through and get total out*)
  876. GetElmtAdr(PrnList,J,P,Code,Size);
  877. TotalDue := TotalDue + P^.Invoice.AMTOUT;
  878. END;
  879. InitDisplayFrame(PymtDF,CurrentWindow);
  880. ReadDisplayFrame(PMIScreens,PymtDF,'Pymts');
  881. GetFieldRec(PymtDF,FieldNum(PymtDF,'PymtAmt'),FldRec); (* make max amout*)
  882. FldRec.rMax := TotalDue;
  883. FldRec.decimalPlace := 2;
  884. PutFieldRec(FldRec,PymtDF,FieldNum(PymtDF,'PymtAmt'));
  885. SetCustOutStd(TotalDue);
  886. ChangeField(PymtDF,TodayStr,'PymtDate',TRUE);
  887. ShowDisplayFrame(PymtDF,0,0,0,0);
  888. DisplayInvList(PrnList);
  889. Control(PymtDF);
  890. (* if the user selected manual payments *)
  891. (* then select which invoice to pay *)
  892. (* otherwise select invoices until payments *)
  893. (* reach zero *)
  894. ReadInput(PymtDF,CheckNbr,'ChkNumber');
  895. ReadRealField(PymtDF,PymtAmount,'PymtAmt');
  896. ReadDateField(PymtDF,PymtDate,'PymtDate');
  897. GetFieldRec(PymtDF,FieldNum(PymtDF,'Manual'),FldRec);
  898. SetCustOutStd(TotalDue-PymtAmount);
  899. OpenPaymentsDBF(TRUE);
  900. OpenOrderDBF(TRUE);
  901. REPEAT (* loop through here until the full payment is used *)
  902. (* can not enter a payment greater than total due *)
  903. IF FldRec.selected (* manual invoice entry *)
  904. THEN
  905. SelectInvoiceFromList(PrnList,FALSE); (* take selected *)
  906. IF CurrentInvoice.INVOICE[0] = 0C (* nothing selected *)
  907. THEN
  908. GetElmtAdr(PrnList,1,P,Size,Code); (* or take the first *)
  909. CurrentInvoice := P^.Invoice;
  910. ReadDBRec(InvoiceDBF,P^.LI); (* set the file to correct invoice*)
  911. PymtAmount := 0.0;
  912. END;
  913. ELSE
  914. GetElmtAdr(PrnList,1,P,Size,Code); (* or take the first *)
  915. CurrentInvoice := P^.Invoice;
  916. ReadDBRec(InvoiceDBF,P^.LI); (* set the file to correct invoice*)
  917. END;
  918. ListDelete(PrnList,ElmtNow(PrnList),1);(* delete the chosen invoice from the list *)
  919. Remaining := PymtAmount - CurrentInvoice.AMTOUT;
  920. IF PymtAmount >= CurrentInvoice.AMTOUT
  921. THEN
  922. MakePayment(CurrentInvoice.INVOICE,PymtDate,CurrentInvoice.AMTOUT,
  923. CheckNbr,CurrentInvoice.CUSTID);
  924. CurrentInvoice.AMTOUT := 0.0; (* pay in full *)
  925. CurrentInvoice.INVPRNT := 'C'; (* closed *)
  926. PostSales(CurrentInvoice.INVOICE);
  927. DeleteInvItems(CurrentInvoice.INVOICE);
  928. ELSE
  929. MakePayment(CurrentInvoice.INVOICE,PymtDate,PymtAmount,
  930. CheckNbr,CurrentInvoice.CUSTID);
  931. CurrentInvoice.AMTOUT := CurrentInvoice.AMTOUT - PymtAmount;
  932. IF CurrentInvoice.AMTOUT < 0.01 (* rounding remainder *)
  933. THEN
  934. CurrentInvoice.AMTOUT := 0.0;
  935. CurrentInvoice.INVPRNT := 'C'; (* close *)
  936. PostSales(CurrentInvoice.INVOICE);
  937. DeleteInvItems(CurrentInvoice.INVOICE);
  938. END;
  939. END;
  940. MoveInvoiceToDBF(CurrentInvoice);
  941. WriteDBRec(InvoiceDBF);
  942. IF FldRec.selected AND (Remaining > 0.01) (* manual invoice entry *)
  943. THEN
  944. DisplayInvList(PrnList); (* display remaining invoice *)
  945. END;
  946. PymtAmount := Remaining;
  947. UNTIL (PymtAmount < 0.01); (* go through until out of money *)
  948. CloseDisplayFrame(PymtDF);
  949. ClosePaymentsDBF();
  950. CloseOrderDBF();
  951. IF NOT FldRec.selected
  952. THEN (* remove for automatic payments *)
  953. CloseDisplayFrame(SummaryDF);
  954. END;
  955. DisposeList(PrnList);
  956. CloseInvoiceDBF();
  957. END PayInvoice;
  958. PROCEDURE CancelInvoice();
  959. VAR
  960. CustID : ARRAY[0..10] OF CHAR;
  961. TheList : GenList;
  962. J : CARDINAL;
  963. Size,Code : CARDINAL;
  964. BEGIN
  965. FOR J := 1 TO ListLength(OrderItemLst) DO
  966. GetElmtAdr(OrderItemLst,J,CurrentItem,Size,Code);
  967. IF NOT Special(CurrentItem^.ItemOrderRec.ITEMNBR)
  968. THEN
  969. CurrentItem^.InventoryItem.ONHAND :=
  970. CurrentItem^.InventoryItem.ONHAND+CurrentItem^.ItemOrderRec.QNTSOLD;
  971. CurrentItem^.ItemOrderRec.QNTSOLD := 0.0;
  972. UpdateInventory();
  973. END;
  974. END;
  975. DeleteGasFromInv(CurrentInvoice.INVOICE);
  976. DeleteInvItems(CurrentInvoice.INVOICE);
  977. CurrentInvoice.INVPRNT := 'X';
  978. HeaderChanged := TRUE;
  979. END CancelInvoice;
  980. PROCEDURE SaveInvoice();
  981. (* save the invoice header - replace if one is already there*)
  982. VAR
  983. BEGIN
  984. IF NOT HeaderChanged
  985. THEN RETURN;
  986. END;
  987. IF NOT FindInvoiceByInvoice(CurrentInvoice.INVOICE)
  988. THEN
  989. AppendBlank(InvoiceDBF);
  990. END;
  991. MoveInvoiceToDBF(CurrentInvoice);
  992. WriteDBRec(InvoiceDBF);
  993. END SaveInvoice;
  994. PROCEDURE SaveItems();
  995. (* go through the items list and save the items
  996. Then go through the inventory list and update the
  997. inventory records
  998. *)
  999. VAR
  1000. OldList : GenList;
  1001. TmpItem : OrderRec;
  1002. Code: CARDINAL;
  1003. L : LONGINT;
  1004. J, Size,LL : CARDINAL;
  1005. K : CARDINAL;
  1006. Inv : InvtryRec;
  1007. BEGIN
  1008. IF NOT ItemsChanged (* if nothing changed - dont resave the items*)
  1009. THEN
  1010. DisposeList(OrderItemLst);
  1011. RETURN;
  1012. END;
  1013. NewList(OldList); (* first delete any existing entries *)
  1014. (* find the position of the inventory item id in the record *)
  1015. (* so I can adjust the inventory amount by the deleted record *)
  1016. (* must do this in the case of the update changing the quanity *)
  1017. DeleteInvItems(CurrentInvoice.INVOICE);
  1018. (* now update with the new entries *)
  1019. LL := ListLength(OrderItemLst);
  1020. FOR J := 1 TO LL DO
  1021. GetElmtAdr(OrderItemLst,J,CurrentItem,Size,Code);
  1022. AppendBlank(OrderDBF);
  1023. MoveOrderToDBF(CurrentItem^.ItemOrderRec);
  1024. WriteDBRec(OrderDBF);
  1025. END;
  1026. END SaveItems;
  1027. PROCEDURE AddInvoice();
  1028. VAR
  1029. Weekday,mmddyy : ARRAY[0..15] OF CHAR;
  1030. BEGIN
  1031. CurrInvOldAmt := 0.0;
  1032. Fill(ADR(CurrentInvoice),SIZE(CurrentInvoice),0);
  1033. GetCustNbr(CurrentInvoice.CUSTID);
  1034. GetCustSalesRep(CurrentInvoice.SALESMAN);
  1035. GetCustTerms(CurrentInvoice.TERMS);
  1036. GetCustShipVia(CurrentInvoice.SHIPVIA);
  1037. GetCustDisCntLvl(CurrentInvoice.DFLTLVL);
  1038. GetCustTaxable(CurrentInvoice.TAXABLE);
  1039. GetCustFreeFrght(CurrentInvoice.FREEFRGHT);
  1040. IF CurrentInvoice.DFLTLVL < 0
  1041. THEN CurrentInvoice.DFLTLVL := 1
  1042. ELSIF CurrentInvoice.DFLTLVL > 3
  1043. THEN CurrentInvoice.DFLTLVL := 3;
  1044. END;
  1045. GetCustDisAmount(CurrentInvoice.INVDSCNT);
  1046. MakeSeqNbr('Invoice',Config.InvoicePre,CurrentInvoice.INVOICE);
  1047. CrunchBlanks(CurrentInvoice.INVOICE);
  1048. CurrentInvoice.INVDATE := Today;
  1049. CurrentInvoice.INVPRNT := 'O'; (* invoice opened *)
  1050. NewList(OrderItemLst);
  1051. UpdateInvHeader();
  1052. HeaderChanged := TRUE;
  1053. AddItems(CurrentInvoice); (* get inventory items *)
  1054. END AddInvoice;
  1055. PROCEDURE ControlInvoice( CtlType : CHAR);
  1056. VAR InvNbr : ARRAY[0..10] OF CHAR;
  1057. FldNum : CARDINAL;
  1058. FldRec : InputFieldRecord;
  1059. CtrlInv : BOOLEAN;
  1060. Size, Code : CARDINAL;
  1061. BEGIN
  1062. CtrlInv := TRUE;
  1063. HeaderChanged := FALSE;
  1064. ItemsChanged := FALSE;
  1065. NewList(OrderItemLst);
  1066. InitDisplayFrame(InvoiceHeadDF,CurrentWindow);
  1067. ReadDisplayFrame(PMIScreens,InvoiceHeadDF,'InvHeader');
  1068. OpenOrderDBF(TRUE);
  1069. OpenInvoiceDBF(TRUE);
  1070. IF (CtlType # 'N')
  1071. THEN SelectInvoice(); (* always select one if not new *)
  1072. IF CurrentInvoice.INVOICE[0] = 0C
  1073. THEN RETURN (* no open invoice *)
  1074. END;
  1075. ELSE AddInvoice();
  1076. END;
  1077. IF (CtlType = 'C')
  1078. THEN CancelInvoice();
  1079. CtrlInv := FALSE;
  1080. END;
  1081. (* CASE CtlType OF
  1082. |'P' : PrintPkg( InvNbr);
  1083. |'I' : PrintInv(InvNbr);
  1084. |'C' : CancellInv(InvNbr);
  1085. END; *)
  1086. IF CtrlInv
  1087. THEN
  1088. NewList(PullDnMenu);
  1089. LoadFrameList(PMIScreens,'InvoiceMain',PullDnMenu);
  1090. REPEAT
  1091. NextFrame := 'InvoiceMain';
  1092. ControlSeparately(PullDnMenu,NextFrame,SelChar,EndingFrame);
  1093. CASE SelChar OF
  1094. 'H' : ShowDisplayFrame(InvoiceHeadDF,0,0,0,0); (* show bottom part *)
  1095. Control(InvoiceHeadDF); (* edit header *)
  1096. ReadHeader();
  1097. Recompute();
  1098. UpdateInvHeader();
  1099. ShowDisplayFrame(SummaryDF,0,0,0,0);
  1100. |'E' : SelectFromSummary();
  1101. InitDisplayFrame(OrderItemDF,CurrentWindow);
  1102. ReadDisplayFrame(PMIScreens,OrderItemDF,'OrderItem');
  1103. ShowDisplayFrame(OrderItemDF,0,0,0,0);
  1104. FldNum := FieldNum(OrderItemDF,'Item');
  1105. ItemsChanged := TRUE; (* make sure to update the items*)
  1106. GetFieldRec(OrderItemDF,FldNum,FldRec);
  1107. FldRec.typ := 'D'; (* make display field *)
  1108. PutFieldRec(FldRec,OrderItemDF,FldNum);
  1109. UpdateOrd();
  1110. CurrentItem^.OldQuant := CurrentItem^.ItemOrderRec.QNTSOLD;
  1111. ControlFrame(OrderItemDF,2,'',FALSE,NextFrame);
  1112. ReadScrn();
  1113. IF NOT Special(CurrentItem^.ItemOrderRec.ITEMNBR)
  1114. THEN
  1115. IF CurrentItem^.OldQuant <> CurrentItem^.ItemOrderRec.QNTSOLD
  1116. THEN
  1117. CurrentItem^.InventoryItem.ONHAND :=
  1118. CurrentItem^.InventoryItem.ONHAND+
  1119. CurrentItem^.OldQuant;
  1120. CurrentItem^.ItemOrderRec.NOTES1 := ''; (* zero out back orer*)
  1121. CurrentItem^.ItemOrderRec.NOTES2 := '';
  1122. CurrentItem^.ItemOrderRec.NOTES3 := '';
  1123. UpdateInventory();
  1124. END;
  1125. CloseDisplayFrame(OrderItemDF);
  1126. END;
  1127. ShowSummary();
  1128. |'V' : SelectFromSummary(); (* view items *)
  1129. ShowSummary();
  1130. |'A' : CloseDisplayFrame(SummaryDF);
  1131. AddItems(CurrentInvoice);
  1132. |'D' : SelectFromSummary();
  1133. GetElmtAdr(OrderItemLst,ElmtNow(OrderItemLst),CurrentItem,Size,Code);
  1134. IF NOT Special(CurrentItem^.ItemOrderRec.ITEMNBR)
  1135. THEN
  1136. CurrentItem^.InventoryItem.ONHAND :=
  1137. CurrentItem^.InventoryItem.ONHAND+CurrentItem^.ItemOrderRec.QNTSOLD;
  1138. CurrentItem^.ItemOrderRec.QNTSOLD := 0.0;
  1139. UpdateInventory();
  1140. END;
  1141. ListDelete(OrderItemLst,ElmtNow(OrderItemLst),1);
  1142. ShowSummary();
  1143. ItemsChanged := TRUE;
  1144. |'P' : (*SelectFromSummary(); *)
  1145. PrintInvoice(FALSE);
  1146. |'K' : (* Print Packing slip *)
  1147. (* SelectFromSummary(); *)
  1148. PrintInvoice(TRUE);
  1149. |'C' : IF PromptYN('About to cancel invoice - continue',InvoiceHeadDF)
  1150. THEN
  1151. CancelInvoice ();
  1152. SelChar := 'X';
  1153. END;
  1154. END;
  1155. UNTIL SelChar='X'; (* Assumes 'X' is only used to exit *)
  1156. END; (* end if control *)
  1157. (* ClearScreen(); *)
  1158. CloseDisplayFrame(InvoiceHeadDF);
  1159. SaveInvoice();
  1160. SaveItems();
  1161. CloseInvoiceDBF();
  1162. CloseOrderDBF();
  1163. END ControlInvoice;
  1164. END Invoice.
  1165.