It is currently Thu Mar 28, 2024 8:49 am


All times are UTC - 8 hours [ DST ]




Post new topic Reply to topic  [ 1 post ] 
Author Message
 Post subject: Unit 3 - Lesson 2: Create/Edit Database - Exercise 6
PostPosted: Tue Jul 12, 2011 10:32 am 
User avatar

Joined: Wed Nov 17, 2010 8:37 am
Posts: 136
Real Name: Terry L. Wiechmann
Began Programming in MUMPS: 0- 0-1971
Exercise 5 Solution

Routine: MP1PEDIT
Code:
MP1PEDIT ; Create/Edit Parts routine for the MP1 Course.
   New REC,X,PNUM,PDESC,PQTY,PLVL,PRC,PSP,UPPER,LOWER,IEN
   ;
INIT ; Initialize all variables and drop through.
   Set (REC,PNUM,PDESC,PQTY,PLVL,PRC,PSP)=""
   Set IEN=0
   ;
PNUM ; Part Number
   Set X=$$ASK^MP1PVIEW("Part Number",PNUM) ;Ask for Part Number
   If '$$PNUM^MP1PDATA(X) Goto EXIT:X["^" Do  Goto PNUM
   . Write !?5,"Enter 1-6 numeric digits. Required."
   If 'IEN Do
   . Set REC=$$GET^MP1PDATA(X)
   . Set IEN=+REC
   . Set REC=$Piece(REC,";",2,999)
   . Set PDESC=$Piece(REC,"^",2)
   . Set PQTY=$Piece(REC,"^",3)
   . Set PLVL=$Piece(REC,"^",4)
   . Set PRC=$Piece(REC,"^",5)
   . Set PSP=$Piece(REC,"^",6)
   Set PNUM=X
   ;
PDESC ; Description
   Set X=$$ASK^MP1PVIEW("Description",PDESC,1) ;Ask for normalized Part Description
   If '$$PDESC^MP1PDATA(X) Goto PNUM:X["^" Do  Goto PDESC
   . Write !?5,"Enter 1-30 characters starting with a letter. Required."
   Set PDESC=X
   ;
PQTY ; Quantity
   Set X=$$ASK^MP1PVIEW("Quantity",PQTY) ;Ask for Part Quantity
   If '$$PQTY^MP1PDATA(X) Goto PDESC:X["^" Do  Goto PQTY
   . Write !?5,"Enter an integer value. Required."
   Set PQTY=X
   ;
PLVL ; Reorder Level (it's time to reorder the part if PQTY<PLVL)
   Set X=$$ASK^MP1PVIEW("Order Level",PLVL) ;Ask for Part Number
   If '$$PLVL^MP1PDATA(X) Goto PQTY:X["^" Do  Goto PLVL
   . Write !?5,"Enter an integer value. Required."
   Set PLVL=X
   ;
PRC ; Replacement Cost
   Set X=$$ASK^MP1PVIEW("Replacement Cost",PRC) ;Ask for Part Replacement Cost
   If '$$PRC^MP1PDATA(X) Goto PLVL:X["^" Do  Goto PRC
   . Write !?5,"Enter replacement cost in dollars[.cents]"
   Set PRC=X
   ;
PSP ; Selling Price
   Set X=$$ASK^MP1PVIEW("Selling Price",PSP) ;Ask for Part Selling Price
   If '$$PSP^MP1PDATA(X) Goto PRC:X["^" Do  Goto PSP
   . Write !?5,"Enter selling price in dollars[.cents]"
   Set PSP=X
   ;
FEI ; File/Edit/Ignore Entry
   New ERR
   Set X=$$ASK^MP1PVIEW("File, Edit or Ignore","File",1) ;Ask to File, Edit or Ignore
   If X["^" Goto PSP
   If $Extract("EDIT",1,$Length(X))=X Goto PNUM
   If $Extract("IGNORE",1,$Length(X))=X Goto INIT
   If $Extract("FILE",1,$Length(X))=X Do  Goto PNUM:+ERR,INIT
   . Set REC=$$SETREC^MP1PDATA(PNUM,PDESC,PQTY,PLVL,PRC,PSP)
   . Set ERR=$$PUT^MP1PDATA(IEN,REC)
   . Write !,$Piece(ERR,";",2)
   Write " Enter F, E or I."
   Goto FEI
   ;
EXIT ;
   Quit

Routine: MP1XLATE
Code:
MP1XLATE ; Translation functions for MP1 course.
Upper(S) ; Translate the value in the String variable to Uppercase.
   Set S=$Get(S)
   Quit $Translate(S,"abcdefghijklmnopqrstuvwxyz","ABCDEFGHIJKLMNOPQRSTUVWXYZ")
   ;
Lower(S) ; Translate the value in the String variable to Lowercase.
   Set S=$Get(S)
   Quit $Translate(S,"ABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwxyz")
   ;

Routine: MP1PVIEW
Code:
MP1PVIEW ; View routines for MP1 course.
ASK(Prompt,Default,Upper) ; Extrinsic function that asks for a value.
   ; Prompt – Contains prompt displayed to user.
   ; Default – Contains the default valuer to display
   ; Upper – 0 means no normalization to uppercase, 1 means normalization.
   ; Insure that the variable exist if not passed it.
   ; The $Get values are null by default if the second parameter is not specified.
   Set Prompt=$Get(Prompt) ;Default to null if not passed in.
   Set Default=$Get(Default) ;Default to null if not passed in.
   Set Upper=$Get(Upper,0) ;Default to 0 if not passed in.
   New X ; Protect callers X if it exists.
   Write !,Prompt,": "
   Write:Default]"" Default," // "
   Read X
   If X="" Set X=Default ; If null entered, take default
   If Upper Set X=$$Upper^MP1XLATE(X) ; If normalize to upper, call converter.
   Quit X ;Pass back the value to the caller.
   ;

Routine: MP1PDATA
Code:
MP1PDATA ; Model side PUT and GET code for MP1 course
GET(Key,Index) ; Return record based on primary key look up
   ; Determine the correct response to Key being null?
   Set Index=$Get(Index,"B") ;Default to primary index "B".
   New REC
   If $Data(^MP1PARTS(Index,Key)) Do
   . ;Edit entry
   . Set IEN=$Order(^MP1PARTS(Index,Key,""))
   . Set REC=IEN_";"_^MP1PARTS(IEN)
   Else  Do
   . ;Create Entry
   . Set REC=0_";"
   Quit REC
   ;
PUT(IEN,REC) ; File the Parts record.
   ; IEN is either the Internal Entry Number or zero (not defined).
   ; REC is the full record structure.
   New OPNUM,OPDESC
   ; If entry does exist, get the old indice values.
   If IEN Do
   . ;Get original indices values.
   . Set OPNUM=$Piece(^MP1PARTS(IEN),"^",1)
   . Set OPDESC=$Piece(^MP1PARTS(IEN),"^",2)
   ; If entry does not exist, get a new Internal Entry Number (IEN).
   Else  Do
   . ; Init old values to null - new record.
   . Set (OPNUM,OPDESC)=""
   . Lock +^MP1PARTS(0):0 ; Increment lock count on node. Force timeout.
   . Else  Write !?5,"Cannot get next node number – record not filed." Quit
   . If '$Data(^MP1PARTS(0)) Set ^MP1PARTS(0)=0
   . Set (IEN,^MP1PARTS(0))=^MP1PARTS(0)+1
   . Lock -^MP1PARTS(0) ; Decrement lock count on node
   ; Make sure indices do not exist - multiple indices not permitted.
   If PNUM'=OPNUM,$Data(^MP1PARTS("B",PNUM)) Do  Quit
   . Write !?5,"Number "_PNUM_" is already being used."
   If PDESC'=OPDESC,$Data(^MP1PARTS("C",PDESC)) Do  Quit
   . Write !?5,"Description "_PDESC_" is already being used."
   ; Lock record node incrementally.
   Lock +^MP1PARTS(IEN):0 ; Increment lock count on record. Force timeout.
   ; If timeout occurred and no lock then pass back record busy message.
   Else  Write !?5,"Record busy – record not filed." Quit
   ; Remove old indices.
   Kill:OPNUM]""&(OPNUM'=PNUM) ^MP1PARTS("B",OPNUM)
   Kill:OPDESC]""&(OPDESC'=PDESC) ^MP1PARTS("C",OPDESC)
   ; Set the new record and indices nodes.
   Set ^MP1PARTS(IEN)=PNUM_"^"_PDESC_"^"_PQTY_"^"_PLVL_"^"_PRC_"^"_PSP
   Set ^MP1PARTS("B",PNUM,IEN)=""
   Set ^MP1PARTS("C",PDESC,IEN)=""
   ; Incrementally unlock record node.
   Lock -^MP1PARTS(IEN) ; Decrement lock count on node
   Write !?5,"Record filed successfully."
   Quit
   ;
SETREC(PNUM,PDESC,PQTY,PLVL,PRC,PSP) ; Construct Parts record.
   ; Parameters are passed by reference, not value.
   Quit PNUM_"^"_PDESC_"^"_PQTY_"^"_PLVL_"^"_PRC_"^"_PSP
   ;
PNUM(X) ;Check PNUM syntax
   Quit $Select(X?1.6N:1,1:0)
   ;
PDESC(X) ;Check PDESC syntax
   Quit $Select(X?1A.29NAP:1,1:0)
   ;
PQTY(X) ;Check PNUM syntax
   Quit $Select(X?1.N:1,1:0)
   ;
PLVL(X) ;Check PLVL syntax
   Quit $Select(X?1.N:1,1:0)
   ;
PRC(X) ;Check PRC syntax
   Quit $Select(X?.N.1".".2N:1,1:0)
   ;
PSP(X) ;Check PSP syntax
   Quit $Select(X?.N.1".".2N:1,1:0)
   ;

Review
  1. The Model-View-Controller pattern can be used for procedural or object oriented environments. It is most effective when the underlying language supports objects and event and callback handling. Standard MUMPS does not. However, extensions to the MUMPS language do, in particular, the "trigger" concept in GT.M and Events and Callbacks in the EsiObjects OO extensions to MUMPS.
  2. The Model-View-Controller pattern can be somewhat confusing if you've never dealt with it before. In terms of our exercise, we started with all three abstractions tightly bound and ended up with them separated. Basically, all we did was insert code between the View and Model sides and let it drive (control) the process. The controller is responsible for the interface display as well as responding to user actions.
  3. In terms of the Model side, this will be evolved into a miniature database system with data dictionary in the MUMPS Programming II course.
  4. At this point you will be responsible for creating the code on your own. If you followed along closely and did the exercises, you should have enough experience to add the specified functionality.
Goals
  1. Move Error/Help message writes from the controller to view side.
  2. Permit the user to bypass entry of non-required fields.
  3. Permit the user to enter the Part Description at the Part Number number query for lookup.
  4. List out all entries in the database based on entering ″^L″.
Description
  1. We need to finish separating code to conform with the M-V-C pattern. Move all error/help writes to the view side.
  2. Data elements are often required to complete a record. If so, the Create/Edit routine should force the user to enter it. By default the Create/Edit routine requires the user to enter all data elements. However, the Selling Price and Replacement Cost elements are not required. Modify them to permit the user to enter null and pass by them.
  3. When editing a part, you often want to look up a part by it's name. Modify the PNUM query to check for the Part Description and use it to get the record from the database if it exists.
  4. It is helpful to let the user display all Parts currently stored in the database. If the user enters a ″^L″, display all data elements in columns. Make sure to separate the functionality between Model-View-Controller. It is the model side responsibility to walk the tree structure ($Order) and return a record. It is the View's responsibility to display the contents (IO commands and $Y) and it is the Controller responsibility to drive the process.

_________________
Terry L. Wiechmann


Top
Offline Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 1 post ] 

All times are UTC - 8 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 8 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Theme created StylerBB.net