/* imp-behave.p - Import Behavior Records */ /* 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 - Building code REQUIRED Building code for stu-behave */ /* # 2 - Student ID REQUIRED SPM ID of the student */ /* # 3 - Behavior code REQUIRED If "require-event" then #9-13 required */ /* # 4 - Behave date REQUIRED Date the incident occurred */ /* # 5 - Behave time REQUIRED Time the incident occurred */ /* # 6 - Personnel Code REQUIRED Code of person reporting event */ /* # 7 - Occurred in school OPTIONAL On school grounds, in school hours */ /* # 8 - Desc of event OPTIONAL Description of the incident */ /* # 9 - Action code OPT/REQ IF #9 = "" Then #10 - 14 ignored, */ /* Otherwise #10 - 14 required */ /* #10 - Bldg of event OPT/REQ Building code for stu-behave-event */ /* #11 - Event date OPT/REQ Date of event */ /* #12 - Event time OPT/REQ Time of event */ /* #13 - Reviewed by OPT/REQ Code of person reviewing event */ /* #14 - Desc of event OPTIONAL Description of event */ /* Include commons */ {common.i NEW} {p-init.i "'IMPORTER'"} {addrutil.i DEFINE} {timeutil.i DEFINE} /* Constants */ &SCOPED WriteCmd PUT STREAM LogStream UNFORMATTED &SCOPED WriteHdr "#" LineCnt ", " ImportText[1] ", " ImportText[2] ": " &SCOPED WriteLog {&WriteCmd} {&WriteHdr} /* Define Variables */ DEFINE VARIABLE SchoolYearName AS CHARACTER NO-UNDO. 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 ErrorCount AS INTEGER NO-UNDO. DEFINE VARIABLE Elapsed AS CHARACTER NO-UNDO. DEFINE VARIABLE TimeRemain AS CHARACTER NO-UNDO. /* Definevariable for import text checking */ DEFINE VARIABLE BehaviorEvent AS LOGICAL NO-UNDO. DEFINE VARIABLE CreateBehaveCode AS LOGICAL NO-UNDO. DEFINE VARIABLE CreateActionCode AS LOGICAL NO-UNDO. DEFINE VARIABLE BehaveBldgID LIKE stu-behave.bldg-id NO-UNDO. DEFINE VARIABLE BehaveDate LIKE stu-behave.behave-date NO-UNDO. DEFINE VARIABLE BehaveTime LIKE stu-behave.behave-time NO-UNDO. DEFINE VARIABLE TimeOk AS LOGICAL NO-UNDO. DEFINE VARIABLE RawTime AS INTEGER NO-UNDO. DEFINE VARIABLE InSchool AS LOGICAL NO-UNDO. DEFINE VARIABLE EventBldgID LIKE stu-behave-event.bldg-id NO-UNDO. DEFINE VARIABLE EventDate LIKE stu-behave-event.event-date NO-UNDO. DEFINE VARIABLE EventTime LIKE stu-behave-event.event-time NO-UNDO. /* Define Buffers */ DEFINE BUFFER SchoolYear FOR school-year. DEFINE BUFFER BehaveBldg FOR building. DEFINE BUFFER StuBase FOR stu-base. DEFINE BUFFER StuYear FOR stu-year. DEFINE BUFFER BehaveCode FOR behave-code. DEFINE BUFFER BehaveAction FOR behave-action. DEFINE BUFFER EventBldg FOR building. DEFINE BUFFER StuBehave FOR stu-behave. DEFINE BUFFER StuBehaveEvent FOR stu-behave-event. DEFINE BUFFER BehavePersonnel FOR personnel. DEFINE BUFFER EventPersonnel FOR personnel. DEFINE BUFFER PersonnelBldg FOR personnel-bldg. DEFINE BUFFER AltBehaveCode FOR behave-code. DEFINE BUFFER AltBehaveAction FOR behave-action. /* 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" ErrorCount 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) " Behavior Importation Statistics ". /* First, get the import file */ QueryBlock: DO WHILE TRUE ON ERROR UNDO, RETURN ON ENDKEY UNDO, RETURN: /* Define the form */ FORM SchoolYearName LABEL " School year to import to" FORMAT "x(9)" 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 8 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 SchoolYearName LABEL " School year to import to" FORMAT "x(9)" 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 8 SIDE-LABELS COLOR VALUE(the-color.c-proc) PROMPT VALUE(the-color.c-input) TITLE COLOR VALUE(the-color.c-title) " Import Student Behavior Records ". /* See if the note exists */ IF SEARCH(ImportFile) = ? THEN DO: BELL. {safe-msg.i "'Cannot find the import source file'"} NEXT. END. /* Load the school year buffer */ FIND FIRST SchoolYear WHERE SchoolYear.school-year-name = SchoolYearName NO-LOCK NO-ERROR. IF NOT AVAILABLE SchoolYear THEN DO: BELL. {safe-msg.i "'School year not on 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. /* QueryBlock */ /* 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: /* Clear variables */ ASSIGN BehaviorEvent = NO CreateActionCode = NO CreateBehaveCode = NO ImportText = "". /* Get a line */ 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 ErrorCount STRING(TIME - StartTime, "HH:MM:SS") @ Elapsed STRING(INTEGER((TotalLineCnt - LineCnt) / (LineCnt / (TIME - StartTime))), "HH:MM:SS") @ TimeRemain WITH FRAME StatusFrame. LastUpdate = TIME. END. /* Check required fields are not empty */ 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] = ?) THEN DO: ErrorCount = ErrorCount + 1. {&WriteLog} "One or more REQUIRED fields (1-6) missing, NOT imported" SKIP. NEXT ImportLoop. END. /* Lookup the building, ImportText[1] */ FIND FIRST BehaveBldg OF SchoolYear WHERE BehaveBldg.bldg-code = ImportText[1] NO-LOCK NO-ERROR. IF NOT AVAILABLE BehaveBldg THEN DO: {&WriteLog} "Building not on file, NOT imported" SKIP. ErrorCount = ErrorCount + 1. NEXT ImportLoop. END. /* Set the building-id */ BehaveBldgID = BehaveBldg.bldg-id. /* Lookup the student, ImportText[2] */ FIND StuBase WHERE StuBase.stu-id = ImportText[2] NO-LOCK NO-ERROR. IF AVAILABLE StuBase THEN FIND StuYear OF SchoolYear WHERE StuYear.stu-seq = StuBase.stu-seq NO-LOCK NO-ERROR. IF NOT AVAILABLE StuBase OR NOT AVAILABLE StuYear THEN DO: {&WriteLog} "Student not on file, NOT imported" SKIP. ErrorCount = ErrorCount + 1. NEXT ImportLoop. END. /* Lookup behave code, ImportText[3] */ FIND FIRST BehaveCode OF BehaveBldg WHERE BehaveCode.behave-code-name = ImportText[3] NO-ERROR. IF NOT AVAILABLE BehaveCode THEN IF AutoCreate THEN /* Set flag to create behave-code record after other checking */ CreateBehaveCode = YES. ELSE DO: ErrorCount = ErrorCount + 1. {&WriteLog} "Behave code (3) not on file, NOT imported" SKIP. NEXT ImportLoop. END. ELSE DO: /* Check if require-event and data in related fields */ IF BehaveCode.require-event THEN IF ImportText[9] = "" OR ImportText[9] = ? THEN DO: ErrorCount = ErrorCount + 1. {&WriteLog} "REQUIRED event field, (9) missing, NOT imported" SKIP. NEXT ImportLoop. END. END. /* Check and convert the behave date. ImportText[4] */ BehaveDate = DATE(ImportText[4]) NO-ERROR. IF ERROR-STATUS:ERROR THEN DO: {&writeLog} "Bad date (4), NOT imported" SKIP. ErrorCount = ErrorCount + 1. NEXT ImportLoop. END. /* Check and convert the behave time, ImportText[5] */ {timeutil.i VERIFY ImportText[5] TimeOK} IF NOT TimeOK THEN DO: ErrorCount = ErrorCount + 1. {&WriteLog} "Bad time (5), NOT imported" SKIP. NEXT ImportLoop. END. ELSE DO: {timeutil.i CONVERT ImportText[5] RawTime} BehaveTime = STRING(RawTime, "HH:MM AM"). END. /* Get the person making the stu-behave entry, ImportText[6] */ FIND FIRST BehavePersonnel OF SchoolYear WHERE BehavePersonnel.personnel-code = ImportText[6] NO-LOCK NO-ERROR. IF NOT AVAILABLE BehavePersonnel OR NOT CAN-FIND(FIRST PersonnelBldg OF SchoolYear WHERE PersonnelBldg.Personnel-id = BehavePersonnel.personnel-id NO-LOCK) THEN DO: {&WriteLog} "Personnel code (6) not on file, NOT imported" SKIP. ErrorCount = ErrorCount + 1. NEXT ImportLoop. END. /* Set the variable for occurred in school ImportText[7] */ InSchool = ImportText[7] BEGINS "Y". /* If Field #9, Action name, is not empty then Fields 10 through 13 must have entries */ IF ImportText[9] <> "" AND ImportText[9] <> ? THEN DO: /* Set flag to check data in these fields */ BehaviorEvent = YES. IF (ImportText[10] = "") OR (ImportText[10] = ?) OR (ImportText[11] = "") OR (ImportText[11] = ?) OR (ImportText[12] = "") OR (ImportText[12] = ?) OR (ImportText[13] = "") OR (ImportText[13] = ?) THEN DO: ErrorCount = ErrorCount + 1. {&WriteLog} "One or more REQUIRED fields (10-13) missing, NOT imported" SKIP. NEXT ImportLoop. END. END. /* Check fields 9 to 14 if that data is required */ IF BehaviorEvent THEN DO: /* Get behave-action code id */ FIND FIRST BehaveAction OF BehaveBldg WHERE BehaveAction.behave-action-name = ImportText[9] NO-ERROR. IF NOT AVAILABLE BehaveAction THEN IF AutoCreate THEN /* Set flag to create behave-action after other checking */ CreateActionCode = YES. ELSE DO: ErrorCount = ErrorCount + 1. {&WriteLog} "Behave action name (9) not on file, NOT imported" SKIP. NEXT ImportLoop. END. /* Get the event building */ FIND FIRST EventBldg OF SchoolYear WHERE EventBldg.bldg-code = ImportText[10] NO-LOCK NO-ERROR. IF NOT AVAILABLE EventBldg THEN DO: ErrorCount = ErrorCount + 1. {&WriteLog} "Event building (10) not on file, NOT imported" SKIP. NEXT ImportLoop. END. ELSE EventBldgID = EventBldg.bldg-id. /* Check and convert the event date */ EventDate = DATE(ImportText[11]) NO-ERROR. IF ERROR-STATUS:ERROR THEN DO: {&writeLog} "Bad date (11), NOT imported" SKIP. ErrorCount = ErrorCount + 1. NEXT ImportLoop. END. /* Check and convert the event time */ {timeutil.i VERIFY ImportText[12] TimeOK} IF NOT TimeOK THEN DO: ErrorCount = ErrorCount + 1. {&WriteLog} "Bad time (12), NOT imported" SKIP. NEXT ImportLoop. END. ELSE DO: {timeutil.i CONVERT ImportText[12] RawTime} EventTime = STRING(RawTime, "HH:MM AM"). END. /* Get the reviewer */ FIND FIRST EventPersonnel OF SchoolYear WHERE EventPersonnel.personnel-code = ImportText[13] NO-LOCK NO-ERROR. IF NOT AVAILABLE EventPersonnel OR NOT CAN-FIND(FIRST PersonnelBldg OF SchoolYear WHERE PersonnelBldg.personnel-id = EventPersonnel.personnel-id NO-LOCK) THEN DO: ErrorCount = ErrorCount + 1. {&WriteLog} "Reviewer personnel code (13) not on file, NOT imported" SKIP. NEXT ImportLoop. END. END. /* BehaviorEvent */ /* Verification is finished, so create behave-code record if auto-create */ IF CreateBehaveCode THEN DO: CREATE BehaveCode. ASSIGN BehaveCode.school-year-id = SchoolYear.school-year-id BehaveCode.bldg-id = BehaveBldg.bldg-id BehaveCode.behave-code-name = CAPS(ImportText[3]) BehaveCode.description = "<< CREATED BY IMPORTER >>". {&WriteLog} "Created behave-code, *" ImportText[3] "*, please check it!" SKIP. END. /* Verification is finished, so create behave-action record if auto-create */ IF CreateActionCode THEN DO: CREATE BehaveAction. ASSIGN BehaveAction.school-year-id = SchoolYear.school-year-id BehaveAction.bldg-id = BehaveBldg.bldg-id BehaveAction.behave-action-name = ImportText[9]. BehaveAction.description = "<< CREATED BY IMPORTER >>". {&WriteLog} "Created behave-action, *" ImportText[9] "*, please check it!" SKIP. END. /* Load the stu-behave occurance if it exists */ FIND FIRST StuBehave OF SchoolYear WHERE StuBehave.bldg-id = BehaveBldgID AND StuBehave.behave-code-id = BehaveCode.behave-code-id AND StuBehave.stu-seq = StuYear.stu-seq AND StuBehave.behave-date = BehaveDate AND StuBehave.behave-time = BehaveTime AND StuBehave.personnel-id = BehavePersonnel.personnel-id AND StuBehave.occured-in-school = InSchool NO-ERROR. IF AVAILABLE StuBehave THEN IF ReplaceMode THEN DO: /* Load the stu-behave-event */ FIND FIRST StuBehaveEvent OF SchoolYear WHERE StuBehaveEvent.bldg-id = EventBldgID AND StuBehaveEvent.stu-seq = StuYear.stu-seq AND StuBehaveEvent.event-date = EventDate AND StuBehaveEvent.event-time = EventTime AND StuBehaveEvent.personnel-id = EventPersonnel.personnel-id AND StuBehaveEvent.behave-action-id = BehaveAction.behave-action-id AND StuBehaveEvent.behave-seq = StuBehave.behave-seq NO-LOCK NO-ERROR. /* Create a backup file */ EXPORT STREAM ExportStream BehaveBldg.bldg-code StuBase.stu-id BehaveCode.behave-code-name StuBehave.behave-date StuBehave.behave-time BehavePersonnel.personnel-code StuBehave.occured-in-school StuBehave.description (IF AVAILABLE BehaveAction THEN BehaveAction.behave-action-name ELSE "") (IF AVAILABLE StuBehaveEvent THEN EventBldg.bldg-code ELSE "") (IF AVAILABLE StuBehaveEvent THEN STRING(StuBehaveEvent.event-date) ELSE "") (IF AVAILABLE StuBehaveEvent THEN STRING(StuBehaveEvent.event-time) ELSE "") (IF AVAILABLE StuBehaveEvent THEN EventPersonnel.personnel-code ELSE "") (IF AVAILABLE StuBehaveEvent THEN StuBehaveEvent.description ELSE ""). END. ELSE DO: /* Don't overwrite existing stu-behave if not in replace mode */ {&WriteLog} "Existing stu-behave occurance for student, NOT imported" SKIP. NEXT ImportLoop. END. ELSE DO: /* Create a new stu-behave record */ CREATE StuBehave. ASSIGN StuBehave.school-year-id = SchoolYear.school-year-id StuBehave.stu-seq = StuBase.stu-seq. END. /* Assign common fields to replace or create record*/ ASSIGN StuBehave.bldg-id = BehaveBldgID StuBehave.behave-code-id = BehaveCode.behave-code-id StuBehave.behave-date = BehaveDate StuBehave.behave-time = BehaveTime StuBehave.personnel-id = BehavePersonnel.personnel-id StuBehave.occured-in-school = ImportText[7] BEGINS "Y" StuBehave.description = ImportText[8]. /* If there is data for a stu-behave-event */ IF BehaviorEvent THEN DO: /* Load the stu-behave-event */ FIND FIRST StuBehaveEvent OF SchoolYear WHERE StuBehaveEvent.bldg-id = EventBldgID AND StuBehaveEvent.stu-seq = StuYear.stu-seq AND StuBehaveEvent.event-date = EventDate AND StuBehaveEvent.event-time = EventTime AND StuBehaveEvent.personnel-id = EventPersonnel.personnel-id AND StuBehaveEvent.behave-seq = StuBehave.behave-seq AND StuBehaveEvent.behave-action-id = BehaveAction.behave-action-id NO-ERROR. IF AVAILABLE StuBehaveEvent THEN DO: IF NOT ReplaceMode THEN DO: /* don't overwrite existing file if not in the replace mode */ {&WriteLog} "Existing stu-behave-event for student, NOT imported" SKIP. NEXT ImportLoop. END. END. ELSE DO: /* Create a new stu-behave-event record */ CREATE StuBehaveEvent. ASSIGN StuBehaveEvent.school-year-id = SchoolYear.school-year-id StuBehaveEvent.stu-seq = StuYear.stu-seq. END. /* Assign common fields to replace or create record */ ASSIGN StuBehaveEvent.bldg-id = EventBldgID StuBehaveEvent.event-date = EventDate StuBehaveEvent.event-time = EventTime StuBehaveEvent.personnel-id = EventPersonnel.personnel-id StuBehaveEvent.description = ImportText[14] StuBehaveEvent.behave-seq = StuBehave.behave-seq StuBehaveEvent.behave-action-id = BehaveAction.behave-action-id. END. /* IF BehaviorEvent */ END. /* ImportLoop */ /* Final statistics update */ DISPLAY LineCnt (LineCnt / TotalLineCnt) * 100 @ PercentDone LineCnt / (TIME - StartTime) @ LinesPerSec ErrorCount 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. /* We are done */ {safe-msg.i "'Import Complete'"} RETURN.