ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

Help me with my logic, please? Keep in mind I am a rookie at this.

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Help me with my logic, please? Keep in mind I am a rookie at this.

    I need to find all active customers with certain type codes: CR RF SW WA. The customer could have all 4.
    IF the customer has CR and RF and they are both inactive, I want this data.
    IF the customer does not have CR or RF, and has either SW or WA or both, I want this data.
    I hate posting my code because I know where I am at in the learning cycle, so it’s embarrassing, but here goes.
    I was told to create the data structures, and I know there is an error because UTCSID ZONED(9);
    UTLCID ZONED(9); were already defined.

    **FREE
    //************************************************** **************
    dcl-f ut210ap disk(*ext) keyed; //customer location file
    dcl-f ut220ap disk(*ext) keyed; //customer services file
    dcl-f lmabrelf disk(*ext) keyed; //land file
    dcl-f lm800ap disk (*ext) keyed; //generic codes file
    dcl-f ut200ap disk (*ext) keyed; //customer master file

    dcl-f rut4001ap disk(*ext) usage(*update:*output) keyed; //workfile

    DCL-S SVC_CR CHAR(2);
    DCL-S SVC_RF CHAR(2);
    DCL-S CUST1 ZONED(9);
    DCL-S CUST2 ZONED(9);
    DCL-S CR_STATUS CHAR(1);
    DCL-S RF_STATUS CHAR(1);
    DCL-C CRCODE 'CR';
    DCL-C RFCODE 'RF';


    DCL-DS KEY800;
    LMCDAP CHAR(2) INZ('UT');
    LMCDTP CHAR(2) INZ('CP');
    CODE9 CHAR(9);
    END-DS;

    DCL-DS KEYCR;
    UTCSID ZONED(9);
    UTLCID ZONED(9);
    CODECR CHAR(2) INZ('CR');
    END-DS;
    DCL-DS KEYRF;
    UTCSID ZONED(9);
    UTLCID ZONED(9);
    CODERF CHAR(2) INZ('RF');
    END-DS;
    DCL-DS KEYSW;
    UTCSID ZONED(9);
    UTLCID ZONED(9);
    CODESW CHAR(2) INZ('SW');
    END-DS;
    DCL-DS KEYWA;
    UTCSID ZONED(9);
    UTLCID ZONED(9);
    CODEWA CHAR(2) INZ('WA');
    END-DS;


    READ UT210AP;
    DOW NOT %EOF(UT210AP);
    //Active customers only
    IF UTCLST = 'A';
    //Commercial type codes
    IF UTCSTP = 'AP' OR UTCSTP = 'B' OR UTCSTP = 'C'
    OR UTCSTP = 'CT' OR UTCSTP = 'E' OR UTCSTP = 'F'
    OR UTCSTP = 'G' OR UTCSTP = 'J';

    CHAIN %KDS(KEYCR) UT220AP; //chained with CR constant
    IF %FOUND(ut220ap);
    SVC_CR = UTSVC;
    CUST1 = UTCSID;
    CR_STATUS = UTSSTS;
    CLEAR SVC_RF;
    CLEAR CUST2;
    CLEAR RF_STATUS;


    CHAIN %KDS(KEYRF) UT220AP; //chained with RF constant
    IF %FOUND(ut220ap);
    IF utsvc = 'RF';
    SVC_RF = UTSVC;
    CUST2 = UTCSID;
    RF_STATUS = UTSSTS;
    ENDIF;

    CHAIN %KDS(KEYSW) UT220AP;
    IF %FOUND(UT220AP);
    CHAIN (UTCSID:UTLCID) RUT4001AP;
    IF NOT %FOUND(RUT4001AP);
    WRITE RUT4001AF;
    ENDIF;
    ENDIF;

    //making sure both codes are for the same customer
    IF CUST1 = CUST2 and CUST1 > 0 and
    CR_STATUS = 'I' AND RF_STATUS = 'I';
    //only want the data with Inactive on both codes
    CHAIN UTLCID LMABRELF; //for address
    IF %FOUND(LMABRELF);
    CODE9 = UTCSTP;
    CHAIN %kds(KEY800) LM800AP; //for Cust type Description
    IF %FOUND(lm800ap);
    CHAIN UTCSID UT200AP; //for customer name
    IF %FOUND(ut200ap);


    WRITE RUT4001AF;
    CLEAR SVC_CR;
    CLEAR SVC_RF;
    CLEAR CUST1;
    CLEAR CUST2;
    CLEAR CR_STATUS;
    CLEAR RF_STATUS;
    ENDIF;
    ENDIF;
    ENDIF;
    ENDIF;
    ENDIF;
    ENDIF;
    ENDIF;
    ENDIF;
    READ ut210ap;

    ENDDO;

    *INLR=*ON;


    __________________________________________________ _________________

  • #2
    Hello RPGNoob,

    We're glad to have you here and to try to help you with questions.

    Here's a tip, though... when you post source code, it helps a lot if you can put [code] before the first line of the code you're including, and [/code] after the last line. If you don't do that, the browser will remove all of the whitespace, which makes the code harder to read. (Take a look at your message and how the code is formatting to understand what I mean.)

    I took the code and manually re-indented it and will post it with code tags as described above to make it easier for people who'd like to help you.

    Code:
    **FREE
    
    //****************************************************************
    dcl-f ut210ap disk(*ext) keyed;  //customer location file
    dcl-f ut220ap disk(*ext) keyed;  //customer services file
    dcl-f lmabrelf disk(*ext) keyed; //land file
    dcl-f lm800ap disk (*ext) keyed; //generic codes file
    dcl-f ut200ap disk (*ext) keyed; //customer master file
    
    dcl-f rut4001ap disk(*ext) usage(*update:*output) keyed;  //workfile
    
    DCL-S SVC_CR CHAR(2);
    DCL-S SVC_RF CHAR(2);
    DCL-S CUST1 ZONED(9);
    DCL-S CUST2 ZONED(9);
    DCL-S CR_STATUS CHAR(1);
    DCL-S RF_STATUS CHAR(1);
    DCL-C CRCODE 'CR';
    DCL-C RFCODE 'RF';
    
    
    DCL-DS KEY800;
      LMCDAP CHAR(2) INZ('UT');
      LMCDTP CHAR(2) INZ('CP');
      CODE9  CHAR(9);
    END-DS;
    
    DCL-DS KEYCR;
      UTCSID ZONED(9);
      UTLCID ZONED(9);
      CODECR CHAR(2) INZ('CR');
    END-DS;
    DCL-DS KEYRF;
      UTCSID ZONED(9);
      UTLCID ZONED(9);
      CODERF CHAR(2) INZ('RF');
    END-DS;
    DCL-DS KEYSW;
      UTCSID ZONED(9);
      UTLCID ZONED(9);
      CODESW CHAR(2) INZ('SW');
    END-DS;
    DCL-DS KEYWA;
      UTCSID ZONED(9);
      UTLCID ZONED(9);
      CODEWA CHAR(2) INZ('WA');
    END-DS;
    
    
    READ UT210AP;
    DOW NOT %EOF(UT210AP);
    
      //Active customers only
      IF UTCLST = 'A';
    
        //Commercial type codes
        IF UTCSTP = 'AP' OR UTCSTP = 'B' OR UTCSTP = 'C'
          OR UTCSTP = 'CT' OR UTCSTP = 'E' OR UTCSTP = 'F'
          OR UTCSTP = 'G'  OR UTCSTP = 'J';
    
          CHAIN %KDS(KEYCR) UT220AP; //chained with CR constant
          IF %FOUND(ut220ap);
    
            SVC_CR = UTSVC;
            CUST1 = UTCSID;
            CR_STATUS = UTSSTS;
            CLEAR SVC_RF;
            CLEAR CUST2;
            CLEAR RF_STATUS;
    
            CHAIN %KDS(KEYRF) UT220AP;  //chained with RF constant
            IF %FOUND(ut220ap);
    
              IF utsvc = 'RF';
                SVC_RF = UTSVC;
                CUST2 = UTCSID;
                RF_STATUS = UTSSTS;
              ENDIF;
    
              CHAIN %KDS(KEYSW) UT220AP;
              IF %FOUND(UT220AP);
                CHAIN (UTCSID:UTLCID) RUT4001AP;
                IF NOT %FOUND(RUT4001AP);
                  WRITE RUT4001AF;
                ENDIF;
              ENDIF;
    
              //making sure both codes are for the same customer
              IF CUST1 = CUST2 and CUST1 > 0 and
                 CR_STATUS = 'I' AND RF_STATUS = 'I';
    
                //only want the data with Inactive on both codes
                CHAIN UTLCID LMABRELF;      //for address
                IF %FOUND(LMABRELF);
                  CODE9 = UTCSTP;
                  CHAIN %kds(KEY800) LM800AP; //for Cust type Description
                  IF %FOUND(lm800ap);
                    CHAIN UTCSID UT200AP;    //for customer name
                    IF %FOUND(ut200ap);
                      WRITE RUT4001AF;
                      CLEAR SVC_CR;
                      CLEAR SVC_RF;
                      CLEAR CUST1;
                      CLEAR CUST2;
                      CLEAR CR_STATUS;
                      CLEAR RF_STATUS;
                    ENDIF;
                  ENDIF;
                ENDIF;
              ENDIF;
            ENDIF;
          ENDIF;
        ENDIF;
      ENDIF;
    
      READ ut210ap;
    
    ENDDO;
    
    *INLR=*ON;
    Thanks for posting!

    Comment


    • #3
      Hi,

      now that I've re-indented the code, I'm trying to figure out how to help you. Bear in mind that nobody on these forums is familiar with your business or how the database tables work in your application. So, I came up with these questions that I need clarification on:

      Originally posted by RPGNoob View Post
      I need to find all active customers with certain type codes: CR RF SW WA. The customer could have all 4.
      From your code, it looks like a customer is considered active if the "customer location file" has UTCLST = 'A' is that correct?

      I don't understand how the 'certain type codes' work, however. Are these also in the "cusomter location file"? Is that what UTCSTP contains? But, it doesn't seem like it because you're doing this instead of checking the 4 codes you name:

      Originally posted by RPGNoob View Post
      Code:
          //Commercial type codes
          IF UTCSTP = 'AP' OR UTCSTP = 'B' OR UTCSTP = 'C'
            OR UTCSTP = 'CT' OR UTCSTP = 'E' OR UTCSTP = 'F'
            OR UTCSTP = 'G'  OR UTCSTP = 'J';
      Since these don't seem to be at all related to the type code being CR RF SW or WA.. How would we know where to find this?

      It does seem like you've coded data structures named KEYCR, KEYRF, KEYSW and KEYWA, which might be intended for this. You seem to be chaining to the "customer services file" with these as hardcoded values. I don't know if these, truly are, the key to that file then I don't think it makes sense to chain with hard-coded values, since those values will always be in your program. This won't tell you if a given customer record has those type codes.

      Can you tell us more about how to determine that?

      Originally posted by RPGNoob View Post
      IF the customer has CR and RF and they are both inactive, I want this data.
      I don't see any logic in your program for whether a customer is inactive, only a check for UTCLST = 'A', which seems to mean "active". Is inactive everything that does not have the 'A'? Or how do you know if a customer is inactive?

      Originally posted by RPGNoob View Post
      IF the customer does not have CR or RF, and has either SW or WA or both, I want this data.
      Can a single customer have multiple type codes? How do you check them and determine that? Is the SW/WA meant only for inactive customers as well?

      Comment


      • #4
        Thanks, I was hoping someone would tell me how to post my code correctly. I hated seeing all the nice formatting disappearing.

        Sorry for being so confusing on the first post. (and most likely on this post)

        My original program worked great. I just had to find customers with CR and RF inactive codes. Here is sample data (from 400).
        Code:
         [TABLE="border: 0, cellpadding: 0, cellspacing: 0"]
        [TR]
        [TD="width: 64"]CUST ID[/TD]
         			[TD="width: 64"]LOC ID[/TD]
         			[TD="width: 64"]SERVICE[/TD]
         			[TD="width: 64"]STATUS[/TD]
         			[TD="width: 64"] [/TD]
         		[/TR]
        [TR]
        [TD]4[/TD]
         			[TD]1[/TD]
         			[TD]RF[/TD]
         			[TD]I[/TD]
         			[TD]inactive[/TD]
         		[/TR]
        [TR]
        [TD]4[/TD]
         			[TD]1[/TD]
         			[TD]SW[/TD]
         			[TD]I[/TD]
         			[TD] [/TD]
         		[/TR]
        [TR]
        [TD]4[/TD]
         			[TD]1[/TD]
         			[TD]WA[/TD]
         			[TD]I[/TD]
         			[TD] [/TD]
         		[/TR]
        [TR]
        [TD]6[/TD]
         			[TD]5[/TD]
         			[TD]CR[/TD]
         			[TD]I[/TD]
         			[TD] [/TD]
         		[/TR]
        [TR]
        [TD]6[/TD]
         			[TD]5[/TD]
         			[TD]RF[/TD]
         			[TD]I[/TD]
         			[TD] [/TD]
         		[/TR]
        [TR]
        [TD]6[/TD]
         			[TD]5[/TD]
         			[TD]YS[/TD]
         			[TD]I[/TD]
         			[TD] [/TD]
         		[/TR]
        [TR]
        [TD]10[/TD]
         			[TD]11[/TD]
         			[TD]RF[/TD]
         			[TD]I[/TD]
         			[TD] [/TD]
         		[/TR]
        [TR]
        [TD]10[/TD]
         			[TD]11[/TD]
         			[TD]SW[/TD]
         			[TD]A[/TD]
         			[TD]Active[/TD]
         		[/TR]
        [TR]
        [TD]10[/TD]
         			[TD]11[/TD]
         			[TD]WA[/TD]
         			[TD]A[/TD]
         			[TD] [/TD]
         		[/TR]
        [/TABLE]
        A customer can have multiple codes. Example, Customer #4 has RF SW WA. My original task was to find the customer with both CR and RF with a service status of Inactive. This was accomplished with this code. Most likely not the best code, but it works. Now I need to get more data. I need the customers without CR and RF.

        Code:
        **FREE
        
        dcl-f ut210ap disk(*ext) keyed;  //customer location file
        dcl-f ut220ap disk(*ext) keyed;  //customer services file
        dcl-f lmabrelf disk(*ext) keyed; //land file
        dcl-f lm800ap disk (*ext) keyed; //generic codes file
        dcl-f ut200ap disk (*ext) keyed; //customer master file
        
        dcl-f rut4001ap disk(*ext) usage(*update:*output);  //workfile
        
        DCL-S SVC_CR CHAR(2);
        DCL-S SVC_RF CHAR(2);
        DCL-S CUST1 ZONED(9);
        DCL-S CUST2 ZONED(9);
        DCL-S CR_STATUS CHAR(1);
        DCL-S RF_STATUS CHAR(1);
        DCL-C CRCODE 'CR';
        DCL-C RFCODE 'RF';
        
        
        DCL-DS KEY800;
             LMCDAP CHAR(2) INZ('UT');
             LMCDTP CHAR(2) INZ('CP');
             CODE9  CHAR(9);
        END-DS;
        
               READ UT210AP;
               DOW NOT %EOF(UT210AP);
        
                  IF UTCLST = 'A';   //Active customers only
        
                     //Commercial type codes
                     IF UTCSTP = 'AP' OR UTCSTP = 'B' OR UTCSTP = 'C'
                     OR UTCSTP = 'CT' OR UTCSTP = 'E' OR UTCSTP = 'F'
                     OR UTCSTP = 'G'  OR UTCSTP = 'J';
        
                       CHAIN (UTCSID:UTLCID:CRCODE) UT220AP; //chained with CR constant
                       IF %FOUND(ut220ap);
                           IF utsvc = 'CR';
                            SVC_CR = UTSVC;
                            CUST1 = UTCSID;
                            CR_STATUS = UTSSTS;
                            CLEAR SVC_RF;
                            CLEAR CUST2;
                            CLEAR RF_STATUS;
                           ENDIF;
        
                        CHAIN (UTCSID:UTLCID:RFCODE) UT220AP;  //chained with RF constant
                        IF %FOUND(ut220ap);
                           IF utsvc = 'RF';
                            SVC_RF = UTSVC;
                            CUST2 = UTCSID;
                            RF_STATUS = UTSSTS;
                           ENDIF;
                                           //making sure both codes are for the same customer
                         IF CUST1 = CUST2 and CUST1 > 0 and
                            CR_STATUS = 'I' AND RF_STATUS = 'I';
                                           //I only want the data with Inactive on both codes
        
                         CHAIN UTLCID LMABRELF;      //for address
                         IF %FOUND(LMABRELF);
                         CODE9 = UTCSTP;
                         CHAIN %kds(KEY800) LM800AP; //for Cust type Description
                         IF %FOUND(lm800ap);
                         CHAIN UTCSID UT200AP;    //for customer name
                         IF %FOUND(ut200ap);
        
        
                            WRITE RUT4001AF;
                            CLEAR SVC_CR;
                            CLEAR SVC_RF;
                            CLEAR CUST1;
                            CLEAR CUST2;
                            CLEAR CR_STATUS;
                            CLEAR RF_STATUS;
                            ENDIF;
                            ENDIF;
                          ENDIF;
                         ENDIF;
                      ENDIF;
                    ENDIF;
                  ENDIF;
                 ENDIF;
               READ ut210ap;
        
               ENDDO;
        
               *INLR=*ON;


        Comment


        • #5
          I just added a couple lines on my IF statements and got the data I needed. If you can understand it and have a better way, please let me know. Trying to get better here.

          Code:
          CHAIN (UTCSID:UTLCID:CRCODE) UT220AP; //chained with CR constant
                         IF %FOUND(ut220ap);
                             IF utsvc = 'CR';
                              SVC_CR = UTSVC;
                              CUST1 = UTCSID;
                              CR_STATUS = UTSSTS;
                              CLEAR SVC_RF;
                              CLEAR CUST2;
                              CLEAR RF_STATUS;
                             ENDIF;
                         Elseif NOT %found(ut220ap);
                           No_CR = 1;
          
          
          
                          CHAIN (UTCSID:UTLCID:RFCODE) UT220AP;  //chained with RF constant
                          IF %FOUND(ut220ap);
                             IF utsvc = 'RF';
                              SVC_RF = UTSVC;
                              CUST2 = UTCSID;
                              RF_STATUS = UTSSTS;
                             ENDIF;
                          Elseif NOT %Found(ut220ap);
                            No_RF = 1;

          Comment


          • #6
            Just a suggestion ...
            Code:
                           IF %FOUND(ut220ap)
                               IF utsvc = 'CR';
                                 SVC_CR = UTSVC;
                                 ...
                               ENDIF;
                           Elseif NOT %found(ut220ap);
                             No_CR = 1;
            Instead of using ELSEIF here, I think it would be clearer to just use ELSE. The ELSEIF is the opposite of the IF here, so it will either go into the IF or the ELSE, but the ELSEIF, makes me want to look further down in the code to see if there are any more ELSEIF or ELSE statements (that would never be reached). Also, by coding the %FOUND expression on the ELSEIF, someone reading the code has to look carefully to see that the ELSEIF has the same %FOUND as the IF.
            Code:
                           IF %FOUND(ut220ap)
                               IF utsvc = 'CR';
                                 SVC_CR = UTSVC;
                                 ...
                               ENDIF;
                           Else;
                             No_CR = 1;
                             ...
            Altermatively, you could combine the two IF's in the first part into IF+AND, and then it would be correct to use ELSEIF for the second part to avoid going into the ELSEIF if the record was found but utsvc wasn't 'CR'.
            Code:
                           IF %FOUND(ut220ap)
                           AND utsvc = 'CR';
                             SVC_CR = UTSVC;
                              ...
                           Elseif NOT %found(ut220ap);
                             No_CR = 1;
                              ...
            I kind of like the simplicity of the IF+ELSE with the nested IFs rather than the more complex IF+AND+ELSEIF. But I can usually argue with myself for hours over the best way to code a complex IF statement :-D

            Comment


            • #7
              Thank you Barbara!

              Comment

              Working...
              X