/* imp-contact.p - Import Contacts */ /* Format of an import line: */ /* NOTE: If you do not have data for an item, replace the field with */ /* a '-'. DO NOT put bogus data in there as it is used when */ /* looking at a record to determine it's intent! */ /* */ /* # 1 - Student ID REQUIRED SPM ID of the student to record note for*/ /* # 2 - Contact Code REQUIRED contact code to import under */ /* # 3 - Contact Name REQUIRED Name of contact */ /* # 4 - Lives w/student REQUIRED Yes or No (if yes, address is ignored) */ /* # 5 - Auth For Care REQUITED Authorized for care Yes or No */ /* # 6 - Head of House REQUIRED Yes or No (only 1 contact can be head) */ /* # 7 - Mailings REQUIRED All, List of mailing classes or None */ /* # 8 - Street # OPTIONAL Ignored if #4 == Yes */ /* # 9 - Street Name OPTIONAL Ignored if #4 == Yes */ /* #10 - Apartment OPTIONAL Ignored if #4 == Yes */ /* #11 - City OPTIONAL Ignored if #4 == Yes */ /* #12 - State OPTIONAL Ignored if #4 == Yes */ /* #13 - Zip Code OPTIONAL Ignored if #4 == Yes */ /* #14 - Home Phone OPTIONAL Ignored if #4 == Yes */ /* #15 - Work Phone OPTIONAL */ /* #16 - Contact Type REQUIRED Complete, Address, Phone or Name */ /* #17 - Comments OPTIONAL Comments for note */ /* #18 - Contact Order OPTIONAL */ /* #19 - Fax Phone OPTIONAL */ /* #20 - Cellular Phone OPTIONAL */ /* #21 - Pager Phone OPTIONAL */ /* #22 - Prefered Phone OPTIONAL Defaults to "Work" */ /* Include commons */ {common.i NEW} {p-init.i "'IMPORTER'"} {addrutil.i DEFINE} /* Constants */ &SCOPED WriteCmd PUT STREAM LogStream UNFORMATTED &SCOPED WriteHdr "#" LineCnt ", " ImportText[1] ", " ImportText[2] ": " &SCOPED WriteLog {&WriteCmd} {&WriteHdr} /* Define Variables */ DEFINE VARIABLE ImportFile AS CHARACTER NO-UNDO. DEFINE VARIABLE ExportFile AS CHARACTER NO-UNDO. DEFINE VARIABLE LogFile AS CHARACTER NO-UNDO. DEFINE VARIABLE ReplaceMode AS LOGICAL NO-UNDO. DEFINE VARIABLE ImportText AS CHARACTER EXTENT 50 NO-UNDO. DEFINE VARIABLE LineCnt AS INTEGER NO-UNDO. DEFINE VARIABLE AutoCreate AS LOGICAL NO-UNDO. /* Variables for statistics */ DEFINE VARIABLE TotalLineCnt AS INTEGER NO-UNDO. DEFINE VARIABLE StartTime AS INTEGER NO-UNDO. DEFINE VARIABLE LastUpdate AS INTEGER NO-UNDO. DEFINE VARIABLE PercentDone AS DECIMAL NO-UNDO. DEFINE VARIABLE LinesPerSec AS DECIMAL NO-UNDO. DEFINE VARIABLE ErrorCnt AS INTEGER NO-UNDO. DEFINE VARIABLE Elapsed AS CHARACTER NO-UNDO. DEFINE VARIABLE TimeRemain AS CHARACTER NO-UNDO. DEFINE VARIABLE TheClass AS CHARACTER NO-UNDO. DEFINE VARIABLE TheClassPtr AS INTEGER NO-UNDO. DEFINE VARIABLE MailingData AS CHARACTER NO-UNDO. DEFINE VARIABLE SetAddress AS LOGICAL NO-UNDO. DEFINE VARIABLE SetPhone AS LOGICAL NO-UNDO. DEFINE VARIABLE ContactNum AS INTEGER NO-UNDO. /* Define Buffers */ DEFINE BUFFER AltContact FOR stu-contact. /* Define Streams */ DEFINE STREAM ImportStream. DEFINE STREAM LogStream. DEFINE STREAM ExportStream. /* Status frame */ FORM TotalLineCnt COLUMN-LABEL "Total!Lines" FORMAT "zzzzz9" LineCnt COLUMN-LABEL "Curnt!Line" FORMAT "zzzzz9" PercentDone COLUMN-LABEL "%age!Done" FORMAT "zz9.99%" LinesPerSec COLUMN-LABEL "Lines!/sec" FORMAT "zz9.99" ErrorCnt COLUMN-LABEL "Errors" FORMAT "zzzz9" Elapsed COLUMN-LABEL "Elapsed!Time" TimeRemain COLUMN-LABEL "Time!Remain" WITH FRAME StatusFrame 1 DOWN CENTERED ROW 9 OVERLAY COLOR VALUE(the-color.c-proc) TITLE COLOR VALUE(the-color.c-title) " Contact Importation Statistics ". /* First, get the import file */ QueryBlock: DO WHILE TRUE ON ERROR UNDO, RETURN ON ENDKEY UNDO, RETURN: /* Define the form */ FORM ImportFile LABEL " Import from" FORMAT "x(255)" VIEW-AS FILL-IN SIZE 32 BY 1 SPACE(1) ReplaceMode LABEL " Existing records should be" FORMAT "Replaced/Kept" LogFile LABEL " Log import results to" FORMAT "x(255)" VIEW-AS FILL-IN SIZE 32 BY 1 SPACE(1) AutoCreate LABEL " Auto-create codes" FORMAT "Yes/No" SKIP ExportFile LABEL " Backup replaced data to" FORMAT "x(255)" VIEW-AS FILL-IN SIZE 32 BY 1 WITH FRAME QueryFrame OVERLAY 1 DOWN CENTERED ROW 10 SIDE-LABELS COLOR VALUE(the-color.c-proc) PROMPT VALUE(the-color.c-input). /* Default things for the user */ ON LEAVE OF ImportFile IN FRAME QueryFrame DO: /* Define Variables */ DEFINE VARIABLE DotPtr AS INTEGER NO-UNDO. /* Get pointer to decimal */ DotPtr = INDEX(ImportFile:SCREEN-VALUE, "."). IF DotPtr = 0 THEN RETURN. /* Default the log file */ IF LogFile:SCREEN-VALUE = "" THEN LogFile:SCREEN-VALUE = SUBSTR(SELF:SCREEN-VALUE, 1, DotPtr - 1) + ".log". /* Default the backup file */ IF ExportFile:SCREEN-VALUE = "" THEN ExportFile:SCREEN-VALUE = SUBSTR(SELF:SCREEN-VALUE, 1, DotPtr - 1) + ".org". END. /* Query the user */ UPDATE ImportFile LABEL " Import from" FORMAT "x(255)" VIEW-AS FILL-IN SIZE 32 BY 1 SPACE(1) ReplaceMode LABEL " Existing records should be" FORMAT "Replaced/Kept" LogFile LABEL " Log import results to" FORMAT "x(255)" VIEW-AS FILL-IN SIZE 32 BY 1 SPACE(1) AutoCreate LABEL " Auto-create codes" FORMAT "Yes/No" ExportFile LABEL " Backup replaced data to" FORMAT "x(255)" VIEW-AS FILL-IN SIZE 32 BY 1 WITH FRAME QueryFrame OVERLAY 1 DOWN CENTERED ROW 10 SIDE-LABELS COLOR VALUE(the-color.c-proc) PROMPT VALUE(the-color.c-input) TITLE COLOR VALUE(the-color.c-title) " Import Student Contacts ". /* See if the note exists */ IF SEARCH(ImportFile) = ? THEN DO: BELL. {safe-msg.i "'Cannot find the import source file'"} NEXT. END. /* Make sure the backup file should be overwritten */ IF SEARCH(ExportFile) <> ? THEN DO: DO ON ERROR UNDO, NEXT QueryBlock ON ENDKEY UNDO, NEXT QueryBlock: MESSAGE COLOR VALUE(the-color.c-alert) " " ExportFile "already exists " SKIP " Do you want to overwrite it?" SKIP VIEW-AS ALERT-BOX QUESTION BUTTONS YES-NO UPDATE OverwriteFile AS LOGICAL. END. /* Iterate if not okay */ IF NOT OverwriteFile THEN NEXT. END. /* Done */ LEAVE. END. /* Load the profile */ FIND FIRST spm-prof NO-LOCK. /* Get line count */ INPUT STREAM ImportStream THROUGH VALUE("wc -l " + ImportFile). IMPORT STREAM ImportStream ImportText. INPUT STREAM ImportStream CLOSE. TotalLineCnt = INTEGER(ImportText[1]). DISPLAY TotalLineCnt WITH FRAME StatusFrame. /* Open the file */ INPUT STREAM ImportStream FROM VALUE(ImportFile). OUTPUT STREAM LogStream TO VALUE(LogFile) PAGE-SIZE 0. OUTPUT STREAM ExportStream TO VALUE(ExportFile) PAGE-SIZE 0. /* Hide the query frame */ HIDE FRAME QueryFrame NO-PAUSE. /* Reset counters */ ASSIGN StartTime = TIME LastUpdate = StartTime. /* Begin Processing */ ImportLoop: REPEAT ON ERROR UNDO, LEAVE ON ENDKEY UNDO, LEAVE: /* Get a line */ ImportText = "". IMPORT STREAM ImportStream ImportText. LineCnt = LineCnt + 1. /* Update status display */ IF (TIME - LastUpdate) > 2 THEN DO: DISPLAY LineCnt (LineCnt / TotalLineCnt) * 100 @ PercentDone LineCnt / (TIME - StartTime) @ LinesPerSec ErrorCnt STRING(TIME - StartTime, "HH:MM:SS") @ Elapsed STRING(INTEGER((TotalLineCnt - LineCnt) / (LineCnt / (TIME - StartTime))), "HH:MM:SS") @ TimeRemain WITH FRAME StatusFrame. LastUpdate = TIME. END. /* Make sure we have our required fields */ IF (ImportText[1] = "") OR (ImportText[1] = ?) OR (ImportText[2] = "") OR (ImportText[2] = ?) OR (ImportText[3] = "") OR (ImportText[3] = ?) OR (ImportText[4] = "") OR (ImportText[4] = ?) OR (ImportText[5] = "") OR (ImportText[5] = ?) OR (ImportText[6] = "") OR (ImportText[6] = ?) OR (ImportText[7] = "") OR (ImportText[7] = ?) OR (ImportText[16] = "") OR (ImportText[16] = ?) THEN DO: ErrorCnt = ErrorCnt + 1. {&WriteLog} "One or more REQUIRED fields missing, NOT imported" SKIP. NEXT ImportLoop. END. /* Lookup the student */ FIND stu-base WHERE stu-base.stu-id = ImportText[1] NO-LOCK NO-ERROR. IF NOT AVAILABLE stu-base THEN DO: {&WriteLog} "Student ID *NOT* on file, NOT imported" SKIP. ErrorCnt = ErrorCnt + 1. NEXT ImportLoop. END. /* Lookup contact code */ FIND contact-code WHERE contact-code.contact-code = ImportText[2] NO-LOCK NO-ERROR. IF NOT AVAILABLE contact-code THEN IF AutoCreate THEN DO: CREATE contact-code. ASSIGN contact-code.contact-code = CAPS(ImportText[2]) contact-code.description = "<< CREATED BY IMPORTER >>". {&WriteLog} "Created contact code, please check it!" SKIP. END. ELSE DO: ErrorCnt = ErrorCnt + 1. {&WriteLog} "Contact code not on file, contact NOT imported" SKIP. NEXT ImportLoop. END. /* Fill in default contact order */ IF (ImportText[18] = "") OR (ImportText[18] = ?) THEN DO: FIND LAST stu-contact OF stu-base USE-INDEX stu-contact-order NO-LOCK NO-ERROR. IF NOT AVAILABLE stu-contact THEN ImportText[18] = "1". ELSE ImportText[18] = STRING(stu-contact.contact-order + 1). END. /* Load the contact (if any) */ FIND LAST stu-contact OF stu-base WHERE stu-contact.contact-code-id = contact-code.contact-code-id NO-ERROR. IF AVAILABLE stu-contact THEN IF ReplaceMode THEN DO: /* Make up the mailing data */ MailingData = stu-contact.mail-type. IF MailingData = "Some" THEN DO: MailingData = "". FOR EACH stu-contact-mailing OF stu-contact NO-LOCK, mail-class OF stu-contact-mailing NO-LOCK: MailingData = "," + mail-class.mail-class-code. END. SUBSTR(MailingData, 1, 1) = "". END. /* Export it */ EXPORT STREAM ExportStream stu-base.stu-id contact-code.contact-code stu-contact.contact-name stu-contact.lives-with-student stu-contact.authorized-for-care stu-contact.head-of-house MailingData stu-contact.mail-street-num stu-contact.mail-street stu-contact.mail-street-apt stu-contact.mail-city stu-contact.mail-state stu-contact.mail-zip stu-contact.home-phone stu-contact.work-phone stu-contact.contact-type stu-contact.comments stu-contact.contact-order stu-contact.fax-phone stu-contact.cell-phone stu-contact.pager-phone stu-contact.preferred-phone. END. ELSE DO: /* Don't overwrite existing contact if not in replace mode */ {&WriteLog} "Existing contact for student, NOT imported" SKIP. NEXT ImportLoop. END. ELSE DO: /* Create a new contact */ CREATE stu-contact. ASSIGN stu-contact.stu-seq = stu-base.stu-seq stu-contact.contact-code-id = contact-code.contact-code-id. END. /* Get/set the name */ IF (ImportText[3] = "") OR (ImportText[3] = ?) THEN DO: ErrorCnt = ErrorCnt + 1. {&WriteLog} "Missing contact name, NOT imported" SKIP. UNDO ImportLoop, NEXT ImportLoop. END. /* Set the name in place */ stu-contact.contact-name = ImportText[3]. /* Set data based on contact type */ IF ImportText[16] <> "Complete" THEN IF ImportText[16] <> "Address" THEN IF ImportText[16] <> "Phone" THEN IF ImportText[16] <> "Name" THEN DO: ErrorCnt = ErrorCnt + 1. {&WriteLog} "Bad contact type, NOT imported" SKIP. UNDO ImportLoop, NEXT ImportLoop. END. /* Set the contact type */ ASSIGN stu-contact.contact-type = ImportText[16] SetAddress = Yes SetPhone = Yes. /* Set the lives with student flag */ IF (ImportText[4] <> "") AND (ImportText[4] <> ?) THEN stu-contact.lives-with-student = ImportText[4] BEGINS "Y". /* Set the authorized for care flag */ IF (ImportText[5] <> "") AND (ImportText[5] <> ?) THEN stu-contact.authorized-for-care = ImportText[5] BEGINS "Y". /* Set the Head of household flag */ IF (ImportText[6] <> "") AND (ImportText[6] <> ?) THEN DO: /* Set flag */ stu-contact.head-of-house = ImportText[6] BEGINS "Y". /* Clear flag for any other contacts */ IF stu-contact.head-of-house THEN FOR EACH AltContact OF stu-base WHERE (AltContact.head-of-house = Yes) AND (RECID(AltContact) <> RECID(stu-contact)): AltContact.head-of-house = No. END. END. /* Check lives with student */ stu-contact.lives-with-student = ImportText[4] BEGINS "Y". IF stu-contact.lives-with-student THEN ASSIGN stu-contact.mail-street-num = stu-base.stu-street-num stu-contact.mail-street = stu-base.stu-street stu-contact.mail-street-apt = stu-base.stu-street-apt stu-contact.mail-city = stu-base.stu-city stu-contact.mail-state = stu-base.stu-state stu-contact.mail-zip = stu-base.stu-zip stu-contact.home-phone = stu-base.stu-phone stu-contact.carrier-route-id = stu-base.carrier-route-id. ELSE IF SetAddress THEN DO: ASSIGN stu-contact.mail-street-num = ImportText[8] stu-contact.mail-street = ImportText[9] stu-contact.mail-street-apt = ImportText[10] stu-contact.mail-city = ImportText[11] stu-contact.mail-state = ImportText[12] stu-contact.mail-zip = ImportText[13]. end. /* Make sure adress is valid */ IF SetAddress AND ((stu-contact.mail-street-num = "") OR (stu-contact.mail-street = "")) THEN DO: ASSIGN stu-contact.mail-street-num = stu-base.stu-street-num stu-contact.mail-street = stu-base.stu-street stu-contact.mail-street-apt = stu-base.stu-street-apt stu-contact.mail-city = stu-base.stu-city stu-contact.mail-state = stu-base.stu-state stu-contact.mail-zip = stu-base.stu-zip. ErrorCnt = ErrorCnt + 1. {&WriteLog} "Contact had bad street name/#, replaced with student address" SKIP. END. /* Make sure the city is OK */ IF SetAddress AND ((stu-contact.mail-city = "") OR (stu-contact.mail-state = "") OR (stu-contact.mail-zip = "")) THEN DO: ASSIGN stu-contact.mail-city = stu-base.stu-city stu-contact.mail-state = stu-base.stu-state stu-contact.mail-zip = stu-base.stu-zip. ErrorCnt = ErrorCnt + 1. {&WriteLog} "Contact had bad city/state, replaced from student address" SKIP. END. /* Figure the carrier route */ IF SetAddress AND spm-prof.use-carrier-route AND NOT stu-contact.lives-with-student THEN DO: {addrutil.i LOOKUP stu-contact.mail-street-num stu-contact.mail-street stu-contact.mail-city stu-contact.mail-state stu-contact.mail-zip stu-contact.carrier-route-id} IF stu-contact.carrier-route-id = ? THEN DO: ErrorCnt = ErrorCnt + 1. {&WriteLog} "Contact address not in carrier route file" SKIP. END. END. /* Set phones */ IF SetPhone THEN DO: /* Set Phone #s */ RUN SetPhone(ImportText[14], INPUT-OUTPUT stu-contact.home-phone). RUN SetPhone(ImportText[15], INPUT-OUTPUT stu-contact.work-phone). RUN SetPhone(ImportText[19], INPUT-OUTPUT stu-contact.fax-phone). RUN SetPhone(ImportText[20], INPUT-OUTPUT stu-contact.cell-phone). RUN SetPhone(ImportText[21], INPUT-OUTPUT stu-contact.pager-phone). /* Set the preferred phone */ IF (ImportText[22] = "") OR (ImportText[22] = ?) THEN ImportText[22] = "Work". TheClassPtr = LOOKUP(ImportText[22], "Work,Home,Fax,Cellular,Pager"). IF TheClassPtr = 0 THEN DO: ErrorCnt = ErrorCnt + 1. {&WriteLog} "Unknown preferred phone number option - CONTACT NOT IMPORTED" SKIP. UNDO ImportLoop, NEXT ImportLoop. END. ImportText[22] = ENTRY(TheClassPtr, "Work,Home,Fax,Cellular,Pager"). RUN SetPreferredPhone(ImportText[22], INPUT-OUTPUT stu-contact.preferred-phone). END. /* Save off comments */ stu-contact.comments = ImportText[17]. /* Set the order */ stu-contact.contact-order = INTEGER(ImportText[18]) NO-ERROR. IF ERROR-STATUS:ERROR THEN DO: ErrorCnt = ErrorCnt + 1. {&WriteLog} "Bad/Invalid contact order #, NOT imported" SKIP. UNDO ImportLoop, NEXT ImportLoop. END. /* Process mailings */ CASE ImportText[7]: WHEN "All" THEN stu-contact.mail-type = "All". WHEN "None" THEN stu-contact.mail-type = "None". OTHERWISE IF (ImportText[7] <> "") AND (ImportText[7] <> ?) THEN DO: /* Set mailing types */ stu-contact.mail-type = "Some". /* Process each type of mailing */ ClassLoop: DO TheClassPtr = 1 TO NUM-ENTRIES(ImportText[7]): /* Extract the item to check */ TheClass = ENTRY(TheClassPtr, ImportText[7]). /* Load/create the mailing class */ FIND mail-class WHERE mail-class.mail-class-code = TheClass NO-LOCK NO-ERROR. IF NOT AVAILABLE mail-class THEN IF AutoCreate THEN DO: CREATE mail-class. ASSIGN mail-class.mail-class-code = CAPS(TheClass) mail-class.description = "<< CREATED BY IMPORTER >>". {&WriteLog} "Created mailing class " CAPS(TheClass) ", please check it!" SKIP. END. ELSE DO: {&WriteLog} "Unknown mailing class code " TheClass ", not added" SKIP. NEXT ClassLoop. END. /* See if the mailing class is associated with the contact */ FIND FIRST stu-contact-mailing OF stu-contact NO-LOCK WHERE stu-contact-mailing.mail-class-id = mail-class.mail-class-id NO-ERROR. IF NOT AVAILABLE stu-contact-mailing THEN DO: CREATE stu-contact-mailing. ASSIGN stu-contact-mailing.stu-seq = stu-contact.stu-seq stu-contact-mailing.stu-contact-seq = stu-contact.stu-contact-seq stu-contact-mailing.mail-class-id = mail-class.mail-class-id. END. END. END. END. END. /* Final statistics update */ DISPLAY LineCnt (LineCnt / TotalLineCnt) * 100 @ PercentDone LineCnt / (TIME - StartTime) @ LinesPerSec ErrorCnt STRING(TIME - StartTime, "HH:MM:SS") @ Elapsed STRING(INTEGER((TotalLineCnt - LineCnt) / (LineCnt / (TIME - StartTime))), "HH:MM:SS") @ TimeRemain WITH FRAME StatusFrame. /* Close the input & log streams */ INPUT STREAM ImportStream CLOSE. OUTPUT STREAM LogStream CLOSE. OUTPUT STREAM ExportStream CLOSE. /* Let them know what's happening */ DISPLAY " Assigning contact order numbers, please be patient... " WITH FRAME ReorderFrame CENTERED ROW 20 OVERLAY COLOR VALUE(the-color.c-title). /* Resequence the contacts */ FOR EACH stu-base NO-LOCK: /* Reset counter */ ContactNum = 0. /* Process all contacts */ REPEAT PRESELECT EACH stu-contact OF stu-base EXCLUSIVE-LOCK BY stu-contact.stu-seq BY stu-contact.contact-order BY stu-contact.stu-contact-seq: /* Load a record */ FIND NEXT stu-contact NO-ERROR. IF NOT AVAILABLE stu-contact THEN LEAVE. /* Assign it a number */ ASSIGN ContactNum = ContactNum + 1 stu-contact.contact-order = ContactNum. END. END. /* Hide the wait frame */ HIDE FRAME ReorderFrame NO-PAUSE. /* We are done */ {safe-msg.i "'Import Complete'"} RETURN. /*** Procedures ***/ /* Process and set a phone # */ PROCEDURE SetPhone: /* Define Parameters */ DEFINE INPUT PARAMETER TheImportPhone AS CHARACTER NO-UNDO. DEFINE INPUT-OUTPUT PARAMETER ThePhone AS CHARACTER NO-UNDO. /* Set home phone */ IF (TheImportPhone <> "") AND (TheImportPhone <> ?) THEN DO: ThePhone = TheImportPhone. /* Fix area codes and prefix */ IF ThePhone BEGINS "1" THEN SUBSTR(ThePhone, 1, 1) = "". IF LENGTH(ThePhone) = 7 THEN ThePhone = " " + ThePhone. END. END. /* Process and set the preferred phone # */ PROCEDURE SetPreferredPhone: /* Define Parameters */ DEFINE INPUT PARAMETER TheImportType AS CHARACTER NO-UNDO. DEFINE INPUT-OUTPUT PARAMETER ThePreferredPhone AS CHARACTER NO-UNDO. /* Iterativly set the import type */ DO WHILE TRUE: CASE TheImportType: WHEN "Home" THEN IF stu-contact.home-phone = "" THEN DO: TheImportType = "Work". NEXT. END. WHEN "Work" THEN IF stu-contact.work-phone = "" THEN DO: TheImportType = "Fax". NEXT. END. WHEN "Fax" THEN IF stu-contact.fax-phone = "" THEN DO: TheImportType = "Cellular". NEXT. END. WHEN "Cellular" THEN IF stu-contact.cell-phone = "" THEN DO: TheImportType = "Pager". NEXT. END. WHEN "Pager" THEN IF stu-contact.pager-phone = "" THEN DO: TheImportType = "Work". LEAVE. END. END. LEAVE. END. ThePreferredPhone = TheImportType. END.