unit wrpunten; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, websession, db, fpjson, idlist, rapporten, sqldb, fpextdirect, webwisa, fpjsonrpc, jsonparser; Const jtMemoPerKlas = 114; type TIntegerPair = array[0..1] of integer; TIntegerpairs = array of TIntegerPair; TPuntenArray = Array[0..17] of TPunt; TCodeData = Class(TObject) Code,Omschrijving : String; Schaal : Integer; BlokkeerIngave, BeperkteEvaluatie : Boolean; end; { TPeriodeData } TPeriodeData = Class(TCodeData) lijst : TStrings; letters, alleenletters, GeenOpmerking, Relatief : boolean; periodetype, Kolom : Integer; opmlengte : integer; Destructor Destroy; override; end; TVakData = Class(TCodeData); { TRPCPunten } TRPCPunten = class(TWisaWebRPCModule) QGetMTAndOPmerking: TWisaWebQuery; QGetPeriodeData: TWisaWebQuery; QGetIngaveData: TWisaWebQuery; QGetModifiedData: TWisaWebQuery; QUpdateJobData: TWisaWebQuery; StartIngave: TWisaRPCHandler; QSelLeerlingen: TWisaWebQuery; DBWisa: TWisaWebDatabase; TRWISA: TWisaWebTransaction; QSelLeerlingPunten: TWisaWebQuery; QCheckKlas: TWisaWebQuery; QCheckPeriode: TWisaWebQuery; QCheckVakken: TWisaWebQuery; QInsertJobData: TWisaWebQuery; GetIngaveModel: TWisaRPCHandler; QGetModelData: TWisaWebQuery; GetIngaveData: TWisaRPCHandler; EditIngaveData: TWisaRPCHandler; QGetIngaveDataRecord: TWisaWebQuery; ProcessJob: TWisaRPCHandler; QInsertLeerlingPunten: TWisaWebQuery; QUpdateLeerlingPunten: TWisaWebQuery; CleanJob: TWisaRPCHandler; StartIngaveMemoPerKlas: TWisaRPCHandler; QGetMemos: TWisaWebQuery; QGetMTID: TWisaWebQuery; QInsertMemoJobData: TWisaWebQuery; ProcessComments: TWisaRPCHandler; QGetModifiedMemos: TWisaWebQuery; QInsertMemo: TWisaWebQuery; QUpdateMemoPointer: TWisaWebQuery; QDeleteMemo: TWisaWebQuery; QUpdateMemo: TWisaWebQuery; GetPuntenboekjeInstallVersion: TWisaRPCHandler; PreparePuntenboekForDownload: TWisaRPCHandler; QGetKastPSFromDocument: TWisaWebQuery; GetSyncServerConfig: TWisaRPCHandler; GetPuntenboekList: TWisaRPCHandler; QGetPuntenboekjes: TWisaWebQuery; CreatePuntenboekDocument: TWisaRPCHandler; QCreateDocument: TWisaWebQuery; procedure CleanJobExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); procedure CreatePuntenboekDocumentExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); procedure DataModuleCreate(Sender: TObject); procedure EditIngaveDataExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); procedure GetIngaveDataExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); procedure GetIngaveModelExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); procedure GetPuntenboekjeInstallVersionExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); procedure GetPuntenboekListExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); procedure GetSyncServerConfigExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); procedure PreparePuntenboekForDownloadExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); procedure ProcessCommentsExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); procedure ProcessJobExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); procedure StartIngaveExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); procedure StartIngaveMemoPerKlasExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); private { private declarations } SavSelLeerlingen : String; // Lees punten nin in blok, Opmerkingen in stream. Geef LP_ID terug. Function CheckData(KlasID: Integer; Vakken, Periodes: TIDList) : integer; procedure DeleteMemo(ID: Integer); procedure GetMemoTypeIDandComment(JobId: Integer); function GetMTIDFromMRID(MRID: Integer; Out Opm : string): Integer; function GetPeriodeData(PID: Integer): TPeriodeData; function GetPeriodePunt(LL : TIngavePuntenGroepItem; Const ColName : String;out PID: Integer; out Opm : TVakOpmerking): TIngavePunt; function GetPeriodes(IDS: TIDList): TIntegerPairs; function GetPuntenBoekKastId: Integer; function GetRecordData(ID: Integer): TJSONObject; procedure InsertJobData(const AJOBID, ATypeRecord, AInteger1: Integer; AMemo: String); procedure InsertLeerlingMemo; function InsertMemo(S: String; LBID: Integer): Integer; procedure LeerlingPunten(LL: TIngavePuntenGroepItem; Vakken: TIDList; Periodes: TIntegerPairs); function LeesLeerlingPunten (LBID, Vak, Blok : Integer; Var Punten : TPuntenArray; Opmerkingen : TStream) : Integer; procedure LoadGroep(JobID: Integer; Groep: TIngavePuntenGroep; AData: String); procedure LoadPeriodeData(PD: TPeriodeData; Q: TWisaWebQuery); procedure MergeIngavePunten(Data: TIDList; Groep: TIngavePuntenGroep); procedure MergePunt(PD: TPeriodeData; PP: TIngavePunt; Opm : TVakOpmerking; D: TJSONData); function ProcessRecordMerge(const ARow: TJSONObject): TJSONObject; procedure PuntenKlas(Volgorde : String;AKlas : Integer; AGroep : TIngavePuntenGroep; Vakken : TIDList; Periodes : TIntegerpairs); procedure SaveGroep(JobID: Integer; Groep: TIngavePuntenGroep); procedure SaveIngavePunten(JID: Integer; Groep: TIngavePuntenGroep); procedure SaveIngavePuntenGroep(JID: Integer; Groep: TIngavePuntenGroep); procedure SaveKolomModel(AJobID: Integer; AGroep: TIngavePuntenGroep; Vakken, Periodes: TIDList; Opmerking : Boolean; Decimals : integer); procedure SaveLeerlingPuntenForEdit(AJobID: Integer; AGroep: TIngavePuntenGroep; Vakken, Periodes: TIDList;Opmerking : Boolean); procedure SaveRecordData(ID: Integer; Data: TJSONObject; MarkDirty: Boolean ); procedure SchrijfLeerlingPunten(ALBID, PMID, AVakId, AB: Integer); procedure UpdateMemo(S: string; MID: Integer); procedure UpdateMemoPointer(JID, MID: Integer); procedure WijzigLeerlingPunten(LPID: Integer; P: TPuntenArray; Opmerking: TStringStream); Protected Class function ActionName : string; override; public { public declarations } end; var RPCPunten: TRPCPunten; implementation uses wwsession, typinfo, cfgWebwisad; {$R *.lfm} Const AantalPeriodes = 18; Procedure ClearPunten(Var P : TPuntenArray); Var I : Integer; begin For I:=Low(P) to High(P) do P[i]:=-1; end; { TPeriodeData } destructor TPeriodeData.Destroy; begin FreeAndNil(Lijst); inherited Destroy; end; { TRPCPunten } Function TRPCPunten.LeesLeerlingPunten(LBID, Vak, Blok : Integer; Var Punten : TPuntenArray; Opmerkingen : TStream) : Integer; Var I : Integer; F : Tfield; begin With QSelLeerlingPunten do begin Close; Params.ParamByName('LP_Loopbaan_FK').AsInteger := LBID; Params.ParamByName('LP_VakOnderdeel_FK').AsInteger := Vak; Params.ParamByName('LP_Blok').AsInteger := Blok; open; try if (EOF and BOF) then begin ClearPunten(Punten); Result:=-1; end else begin // Log('Reading punten'); For I:=0 to 17 do begin F:=QSelLeerlingPunten.FieldByName('LP_PUNT'+IntToStr(i)); If F.IsNull then Punten[I]:=-1 else Punten[I]:=F.AsInteger; end; If Assigned(Opmerkingen) then begin // Log('Reading opmerking. Current : %s',[(Opmerkingen as TStringStream).DataString]); Opmerkingen.Position:=0; If Not QSelLeerlingPunten.FieldByName('LP_OPMERKING').IsNull then (QSelLeerlingPunten.FieldByName('LP_OPMERKING') as TBlobField).SaveToStream(Opmerkingen); Opmerkingen.Position:=0; end; // Log('Getting ID'); Result:=QSelLeerlingPunten.FieldByname('LP_ID').AsInteger; // Log('Done Reading opmerking'); end; finally Close; end; end; end; procedure TRPCPunten.LeerlingPunten(LL : TIngavePuntenGroepItem; Vakken : TIDList; Periodes : TIntegerPairs); Var P : TPuntenArray; VP : TIngaveVakPuntenItem; IP : TIngavePunt; T : TStringStream; I, Vak,LPID : Integer; K, J, Periode, Blok, Kolom : Integer; begin ClearPunten(P); LL.LBID := QSelLeerlingen.FieldByName('LB_ID').AsInteger; LL.Modified := false; for I := 0 to Vakken.Count-1 do begin Vak := Vakken[I]; T:=TStringStream.Create(''); try LPID:=LeesLeerlingPunten(LL.LBID, Vak,0,P,T); Blok:= 0; VP:=LL.Vakpunten.Add as TIngaveVakPuntenItem; VP.VakId :=Vak; VP.Opmerkingen.LoadFromStream(T); Finally T.Free; end; VP.Modified := false; for K := 0 to length(Periodes)-1 do begin Periode := Periodes[K, 0]; if Periode = 0 then break; Kolom := Periodes[K, 1]; J := BerekenBlok(Kolom); if Blok <> J then begin T:=TStringStream.Create(''); LPID:=LeesLeerlingPunten(LL.LBID, Vak, J, P, Nil); Blok:=J; end; J := Kolom mod AantalPeriodes; if J = 0 then J := AantalPeriodes; IP:=VP.PeriodePunten.Add as TIngavePunt; if LPID = 0 then IP.Punt := -1 else if (J>0) and (J<=AantalPeriodes) then IP.Punt:=P[j-1] else IP.Punt := -1; IP.SourceId:=LPID; IP.PeriodeId := Periode; IP.Kolom := Kolom; IP.Modified := false; end; end; end; procedure TRPCPunten.PuntenKlas(Volgorde : String;AKlas : Integer; AGroep : TIngavePuntenGroep; Vakken : TIDList; Periodes : TIntegerPairs); var S : String; LL : TIngavePuntenGroepItem; begin S := SavSelLeerlingen + ' order by '; Volgorde:=Lowercase(Volgorde); if Volgorde = 'iu_stamboeknummer' then S := S + 'IU_Stamboeknummer, KG_Code' else if Volgorde = 'lb_klasnr' then S := S + 'LB_Klasnummer, KG_Code' else if Volgorde = 'll_naamsort' then S := S + 'LL_NaamSort, LL_Voornaamsort, KG_Code' else S := S + 'LL_Naam, LL_Voornaam, KG_Code'; QSelLeerlingen.Sql.Text := S; With QSelLeerlingen do Try Params.ParamByName('KL_ID').AsInteger := aklas; Params.ParamByName('WerkDatum').AsDateTime:=WebwisadConfig.WerkDatum; open; while not Eof do begin LL:=AGroep.Add as TIngavePuntenGroepItem; LeerlingPunten(LL,Vakken,Periodes); next; end; finally close; end; end; Procedure TRPCPunten.LoadPeriodeData(PD : TPeriodeData; Q : TWisaWebQuery); Var O : Integer; begin With Q do begin PD.Code:=FieldByName('PE_CODE').AsString; PD.Omschrijving:=FieldByName('PE_OMSCHRIJVING').AsString; PD.Schaal:=FieldByName('PE_AFDRUKSCHAAL').AsInteger; PD.kolom:=FieldByName('PE_KOLOM').AsInteger; O:=FieldByName('PE_OPTIES').AsInteger; PD.Relatief:=FieldByname('PE_RELATIEVESCHAAL').AsString='+'; PD.BlokkeerIngave:=(O and mpBlokkeerIngave)<>0; PD.BeperkteEvaluatie:=(O and mpBeperkteEvaluatie)<>0; PD.letters:=(O and mpLetterstoestaan)<>0; PD.alleenletters:=(O and mpAlleenLetters)<>0; PD.PeriodeType:=FieldByName(SPeriodeType).AsInteger; if (FindField('MU_MAXOPMERKINGLENGTE')<>Nil) then PD.opmlengte:=FieldByName('MU_MAXOPMERKINGLENGTE').AsInteger; If (PD.PeriodeType=ord(ptLijst)) then begin pd.lijst:=TStringList.Create; pd.lijst.Text:=FieldByName(SPeriodeFormule).AsString; end; end; end; Function TRPCPunten.CheckData(KlasID : Integer; Vakken,Periodes : TIDList) : Integer; Var I,O : Integer; PD : TPeriodeData; VD : TVakData; begin With QCheckKlas do begin ParamByName('KL_ID').AsInteger:=KLasID; ParamByName('PS_ID').AsInteger:=(Session as TWebWisadSession).PSID; ParamByName('SJ_ID').AsInteger:=(Session as TWebWisadSession).SJID; Open; try If (EOF and BOF) then Raise Exception.CreateFmt('Klas %d behoort niet tot uw klassen.',[KlasID]); finally Close; end; end; With QCheckPeriode do begin SQL.Add(Format('AND (PE_ID IN (%s))',[Periodes.AsString])); ParamByName('KL_ID').AsInteger:=KLasID; Open; try While not EOF do begin I:=Periodes.IndexOf(FieldByName('PE_ID').AsInteger); If (I<>-1) then begin PD:=TPeriodeData.Create; LoadPeriodeData(PD,QCheckPeriode); Result:=FieldByName('MP_ID').AsInteger; Periodes.Objects[i]:=PD; end; Next end; finally Close; end; end; For I:=0 to Periodes.Count-1 do if Periodes.Objects[i]=Nil then Raise Exception.CreateFmt('Periode %s behoort niet tot de geselecteerde klas.',[Periodes[i]]) else begin PD:=TPeriodeData(Periodes.Objects[i]); If PD.BlokkeerIngave then Raise Exception.CreateFmt('Periode "%s" is geblokkeerd, er kunnen geen punten voor worden ingegeven.',[PD.Omschrijving]) end; With QCheckVakken do begin SQL.Add(Format('AND (MN_ID IN (%s))',[Vakken.AsString])); ParamByName('KL_ID').AsInteger:=KLasID; ParamByName('PS_ID').AsInteger:=(Session as TWebWisadSession).PSID; Open; try While not EOF do begin I:=Vakken.IndexOf(FieldByName('MN_ID').AsInteger); If (I<>-1) then begin VD:=TVakData.Create; VD.Code:=FieldByName('MN_CODE').AsString; VD.Omschrijving:=FieldByName('MN_OMSCHRIJVING').AsString; VD.Schaal:=FieldByName('MN_AFDRUKOP').AsInteger; O:=FieldByName('MN_OPTIES').AsInteger; VD.BeperkteEvaluatie:=(O and mnBeperkteEvaluatie)<>0; PD.BlokkeerIngave:=(O and mnBlokkeerIngave)<>0; Vakken.Objects[i]:=VD; end; Next; end; finally Close; end; end; For I:=0 to Vakken.Count-1 do if Vakken.Objects[i]=Nil then Raise Exception.CreateFmt('Vak %s behoort niet tot de vakken van de leraar voor de geselecteerde klas.',[Vakken[i]]) else begin VD:=TVakData(Vakken.Objects[i]); If VD.BlokkeerIngave then Raise Exception.CreateFmt('Vak "%s" is geblokkeerd, er kunnen geen punten voor worden ingegeven.',[VD.Omschrijving]) end; end; Function TRPCPunten.GetPeriodes(IDS : TIDList) : TIntegerPairs; Var I : Integer; begin SetLength(Result,IDS.Count); For I:=0 to IDS.Count-1 do begin Result[I,0]:=IDS[i]; Result[I,1]:=TPeriodeData(IDS.Objects[i]).Kolom; end; end; procedure TRPCPunten.SaveGroep(JobID : Integer; Groep : TIngavePuntenGroep); Var T : TStringStream; begin T:=TStringStream.Create(''); try Groep.SaveToStream(T,False); InsertJobData(JobID,3,0,T.DataString); finally T.free; end; end; procedure TRPCPunten.LoadGroep(JobID : Integer; Groep : TIngavePuntenGroep; AData : String); Var T : TStringStream; begin T:=TStringStream.Create(AData); try Groep.LoadFromStream(T); Groep.Modified:=False; finally T.free; end; end; procedure TRPCPunten.StartIngaveExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); Var A,IDS : TJSONArray; Groep : TIngavePuntenGroep; Vakken,PS : TIDList; Periodes : TIntegerPairs; KLasID,JobID,Decimalen, PMID: Integer; Sortering : String; opmerking : boolean; begin Res:=Nil; A:=Params as TJSONArray; KlasID:=A.Integers[0]; IDS:=A.Arrays[1]; Sortering:=A.Strings[4]; Decimalen:=StrToIntDef(A.Strings[3],0); Opmerking:=A.Booleans[5]; If Decimalen<0 then Decimalen:=0 else If Decimalen>2 then Decimalen:=2; Vakken:=TIDList.Create; try ArrayToIDList(IDS,Vakken); PS:=TIDList.Create; try IDS:=A.Arrays[2]; ArrayToIDList(IDS,PS); PMID:=CheckData(KLasID,Vakken,PS); Groep:=TIngavePuntenGroep.Create; try Groep.PeriodeModelID:=PMID; Periodes:=GetPeriodes(PS); PuntenKlas(Sortering,KlasID,Groep,Vakken,Periodes); JobID:=GetNewJobId; InsertJobData(JobID,4,KlasId,Params.AsJSON); SaveKolomModel(JobID,Groep,Vakken,PS,Opmerking,Decimalen); SaveLeerlingPuntenForEdit(JobID,Groep,Vakken,PS,Opmerking); SaveGroep(JobID,Groep); finally Groep.Free; end; finally FreeListObjects(PS); PS.Free end; finally FreeListObjects(Vakken); Vakken.Free; end; Res:=TJSONIntegerNumber.Create(JobID); end; function TRPCPunten.GetMTIDFromMRID (MRID : Integer; Out Opm : string): Integer; begin Result:=0; With QGetMTID do begin Close; ParamByName('MR_ID').AsInteger:=MRID; Open; try if not (EOF and BOF) then Result:=FieldByName('MR_RAPPORTMEMOTYPE_FKP').AsInteger; if (Result=0) then Raise Exception.CreateFmt('Geen geldig rapportmodel ID : %d',[MRID]); OPm:=FieldByname('P_OMSCHRIJVING').AsString; finally close; end; end; end; procedure TRPCPunten.InsertLeerlingMemo; Var Q : TWisaWebQuery; begin Q:=QGetMemos; With QInsertMemoJobData do begin ParamByName('J_INTEGER1').AsInteger:=Q.FieldByname('LB_ID').AsInteger; If Q.FieldByname('BM_ID').IsNull then begin ParamByName('J_INTEGER2').Clear; ParamByName('J_MEMO').Clear; end else begin ParamByName('J_INTEGER2').AsInteger:=Q.FieldByname('BM_ID').AsInteger; ParamByName('J_MEMO').AsString:=Q.FieldByname('BM_MEMO').AsString; end; ParamByName('J_INTEGER3').AsInteger:=Q.FieldByname('IU_ID').AsInteger; ParamByName('J_INTEGER4').AsInteger:=Q.FieldByname('LL_ID').AsInteger; ParamByName('J_INTEGER5').AsInteger:=Q.FieldByname('LB_KLASNUMMER').AsInteger; ParamByName('J_LONGTEXT1').AsString:=Q.FieldByname('LL_NAAM').AsString; ParamByName('J_LONGTEXT2').AsString:=Q.FieldByname('LL_VOORNAAM').AsString; ParamByName('J_SHORTTEXT1').AsString:=Q.FieldByname('IU_STAMBOEKNUMMER').AsString; ExecSQL; end; end; procedure TRPCPunten.StartIngaveMemoPerKlasExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); Var A : TJSONArray; JobID,KLID,MRID,MTID , TypeID : Integer; Opm : String; begin A:=Params as TJSONArray; KLID:=A.Integers[0]; MRID:=A.Integers[1]; TypeID:=A.Integers[2]; if (TypeID<>0) then Raise exception.Create('Type ID moet 0 zijn'); MTID:=GetMTIDFromMRID(MRID,Opm); jobID:=GetNewJobID; With QInsertMemoJobData do begin ParamByName('J_JOBID').AsInteger:=JobID; ParamByName('J_JOBTYPE').AsInteger:=jtMemoPerKlas; ParamByName('J_TYPERECORD').AsInteger:=0; end; With QGetMemos do begin ParamByName('KL_ID').AsInteger:=KLID; ParamByName('WerkDatum').AsDateTime:=WebWisadConfig.WerkDatum; ParamByName('MemoType').AsInteger:=MTID; Open; Try While not EOF do begin InsertLeerlingMemo; Next; end; Finally Close; end; end; With QInsertMemoJobData do begin ParamByname('J_INTEGER1').AsInteger:=MTID; ParamByname('J_INTEGER2').AsInteger:=KLID; ParamByname('J_LONGTEXT1').AsString:=Opm; ParamByName('J_TYPERECORD').AsInteger:=1; ExecSQL; end; Transaction.Commit; Res:=TJSONIntegerNumber.Create(JobID); end; procedure TRPCPunten.SaveLeerlingPuntenForEdit(AJobID : Integer;AGroep : TIngavePuntenGroep; Vakken,Periodes : TIDList;Opmerking : Boolean); Var O : TJSONObject; I,J,K,L,PID,VID,PS,M: Integer; LL : TIngavePuntenGroepItem; V : TVakData; VP : TIngaveVakPuntenItem; P : TPeriodeData; PP : TIngavePunt; W : TJSONFloatNumber; N : TJSONStringType; Opm : TVakopmerking; begin For l:=0 to AGroep.Count-1 do begin LL:=AGroep[l]; O:=TJSONObject.Create; try O.Add('SortField',l); For I:=0 to Vakken.Count-1 do begin VID:=Vakken[i]; V:=Vakken.Objects[i] as TVakData; For J:=0 to Periodes.Count-1 do begin PID:=Periodes[J]; P:=Periodes.Objects[J] as TPeriodeData; if not (P.BeperkteEvaluatie and V.BeperkteEvaluatie) then begin PS:=P.Schaal; If (PS=0) then if P.Relatief then PS:=1 else PS:=10; If P.Relatief then M:=V.Schaal*PS else M:=PS; N:=format('kolom_%d_%d',[VID,PID]); VP:=LL.VakPunten.FindVakByID(VID); If (VP<>Nil) then PP:=VP.PeriodePunten.FindPeriodeByID(PID) else PP:=Nil; If (PP=Nil) or (PP.Punt=-1) then O.Add(N,TJSONNull.Create) else if (PP.Punt>=0) then O.Add(N,PP.Punt/10000*M) else O.Add(N,PuntToStringEx(PP.Punt,M,0,P.lijst)); if Opmerking and (not P.GeenOpmerking) then begin N:=N+'_opm'; Opm:=VP.Opmerkingen.FindPeriodeOpmerking(PID); if Assigned(Opm) then O.Add(N,TJSONString.Create(AnsiToUtf8(Opm.Opmerking))) else O.Add(N,TJSONNull.Create()); end; end; end; end; InsertJobData(AJobID,2,LL.LBID,O.AsJSON); finally O.Free; end; end;; end; procedure TRPCPunten.SaveKolomModel(AJobID : Integer; AGroep : TIngavePuntenGroep; Vakken,Periodes : TIDList; Opmerking : Boolean; Decimals : integer); Function CreateJSArray(L : TStrings) : TJSONArray; Var I : Integer; begin Result:=TJSONArray.Create(); For I:=0 to L.Count-1 do Result.add(L[i]); end; Var O,OM : TJSONObject; A,flds,pick : TJSONArray; I,J,K,PID,VID,PS,M: Integer; V : TVakData; P : TPeriodeData; N : TJSONStringType; begin A:=TJSONArray.Create; try flds:=TJSONArray.Create; try flds.Add(TJSONObject.Create(['name','ID','type','integer'])); flds.Add(TJSONObject.Create(['name','Leerling','type','string'])); flds.Add(TJSONObject.Create(['name','SortField','type','int'])); For I:=0 to Vakken.Count-1 do begin VID:=Vakken[i]; V:=Vakken.Objects[i] as TVakData; For J:=0 to Periodes.Count-1 do begin PID:=Periodes[J]; P:=Periodes.Objects[J] as TPeriodeData; if not (P.BeperkteEvaluatie and V.BeperkteEvaluatie) then begin PS:=P.Schaal; If (PS=0) then if P.Relatief then PS:=1 else PS:=10; If P.Relatief then M:=V.Schaal*PS else M:=PS; N:=format('kolom_%d_%d',[VID,PID]); O:=TJSONObject.Create(['kolom',N, 'vakid',VID, 'vakcode',V.Code, 'vakdesc',V.Omschrijving, 'periodeid',PID, 'periodecode',P.code, 'periodetyoe',P.PeriodeType, 'periodedesc',P.omschrijving, 'decimals',Decimals, 'letters',P.letters, 'alleenletters',p.alleenletters, 'opmerking',false, 'max',m]); if Assigned(P.lijst) then O.Add('picklist',CreateJSArray(P.Lijst)); A.Add(O); flds.Add(TJSONObject.Create(['name',N,'type','auto','useNull', true])); if Opmerking and not P.GeenOpmerking then begin OM:=O.Clone as TJSONObject; // Correcties OM.Strings['kolom']:=N+'_opm'; OM.Booleans['opmerking']:=true; OM.Integers['max']:=p.opmlengte; A.Add(OM); flds.Add(TJSONObject.Create(['name',N+'_opm','type','string'])); end; end; end; end; InsertJobData(AJobID,0,-1,A.AsJSON); InsertJobData(AJobID,1,-1,Flds.AsJSON); finally flds.Free; end; finally A.Free; end; end; procedure TRPCPunten.InsertJobData(Const AJOBID,ATypeRecord,AInteger1 : Integer; AMemo : String); begin With QInsertJobData do begin ParamByName('J_JOBID').AsInteger:=AJobID; ParamByName('J_TYPERECORD').AsInteger:=ATypeRecord; ParamByName('J_INTEGER1').AsInteger:=AInteger1; ParamByName('J_JOBTYPE').AsInteger:=293; // jtPuntenIngaveWeb ParamByName('J_MEMO').AsString:=AMemo; ExecSQL; (QInsertJobData.Transaction as TSQLTransaction).Commit ; end; end; procedure TRPCPunten.DataModuleCreate(Sender: TObject); begin SavSelLeerlingen:=QSelLeerlingen.SQL.Text; end; procedure TRPCPunten.CleanJobExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); Var AJobID : Integer; begin AJObID:=(Params as TJSONArray).integers[0]; (Session as TWisaWebSession).CheckJobID(AJobID); CleanJobTable(AJobID); (Session as TWisaWebSession).RemoveJobID(AJobID); Res:=TJSONBoolean.Create(True); end; procedure TRPCPunten.CreatePuntenboekDocumentExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); Var DID,PSID,KID : Integer; N,FN : String; begin N:=Params.Items[0].AsString; FN:=Params.Items[1].AsString; KID:=GetPuntenBoekKastId; If (KID=-1) then Raise Exception.Create('Geen puntenboek kast beschikbaar'); PSID:=(Session as TWebWisadSession).PSID; If (KID=-1) then Raise Exception.Create('Gebruiker is geen personeelslid'); if (FN='') or (N='') then Raise Exception.Create('Naam of bestandsnaam mogen niet leeg zijn.'); DID:=Gen_ID('GEN_DOCUMENTEN'); With QCreateDocument do begin ParamByName('D_ID').AsInteger:=DID; ParamByName('D_BRON_FK').AsInteger:=PSID; ParamByName('D_KAST_FK').AsInteger:=KID; ParamByName('D_ORIGINELENAAM').AsString:=FN; ParamByName('D_OMSCHRIJVING').AsString:=N; ParamByName('D_NAAM').AsString:=Format('%.8x',[DID])+ExtractFileExt(LowerCase(FN)); ParamByName('D_VERANDERDDOOR').AsInteger:=UserID; ParamByName('D_AANGEMAAKTDOOR').AsInteger:=UserID; ParamByName('D_REFERENTIE1').AsString:=''; ParamByName('D_REFERENTIE2').AsString:=''; ExecSQL; Self.Transaction.Commit; end; Session.AddDocumentID(DID); Res:=TJSONIntegerNumber.Create(DID); end; Function TRPCPunten.GetRecordData(ID : Integer) : TJSONObject; Var D : TJSONData; begin With QGetIngaveDataRecord do begin Close; Params.ParamByname('ID').AsInteger:=ID; Open; try if (EOF and BOF) then Raise EWisaWeb.CreateFmt('Record %d is geen ingave record',[ID]); With TJSONParser.Create(FieldByName('J_MEMO').AsString) do try D:=Parse; If Not (D is TJSONObject) then begin { if (D<>Nil) then Log('Error in memo: '+D.AsJSON); } Raise EWisaWeb.CreateFmt('Record %d bevat geen geldige ingavedata.',[ID]); end; Result:=D as TJSONObject; D:=Nil; finally If (D<>Nil) then D.Free; Free; end; finally Close; end; end; end; Procedure TRPCPunten.SaveRecordData(ID : Integer;Data : TJSONObject;MarkDirty : Boolean); Var D : TJSONData; begin With QUpdateJobData do begin Params.ParamByname('ID').AsInteger:=ID; If MarkDirty then ParamByname('J_BOOLEAN1').AsString:='+' else ParamByname('J_BOOLEAN1').AsString:='-'; Params.ParamByname('J_MEMO').AsString:=Data.AsJSON; ExecSQL; (Transaction as TSQLTransaction).CommitRetaining; end; end; Function TRPCPunten.ProcessRecordMerge(Const ARow : TJSONObject) : TJSONObject; Var ID,I,J,K : Integer; N : String; begin ID:=ARow.Integers['ID']; Result:=GetRecordData(ID); try For I:=0 to Result.Count-1 do begin N:=Result.Names[i]; If Pos('kolom',N)<>0 then begin J:=ARow.IndexOfName(N); If (J<>-1) then Result[N]:=ARow.Items[J].Clone; end; end; SaveRecordData(ID,Result,True); except FreeAndNil(Result); Raise; end; end; procedure TRPCPunten.EditIngaveDataExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); Var O,Row,Data : TJSonObject; Rows,Resp : TJSONArray; I : Integer; begin Res:=Nil; Resp:=Nil; // Rows encoded as data: [{rows: [...]}] try O:=((Params as TJSONArray)[0] as TJSONObject); Resp:=TJSONArray.Create; If O.Types['rows']=jtObject then begin Row:=O.Objects['rows']; Resp.Add(ProcessRecordMerge(Row)); end else begin Rows:=O.Arrays['rows']; For I:=0 to Rows.Count-1 do begin Row:=Rows.Objects[i]; Resp.Add(ProcessRecordMerge(Row)); end; end; Res:=TJSOnObject.Create(['success',true,'data',Resp,'rows',TJSONArray.Create()]); Resp:=nil; except On E : Exception do begin FreeAndNil(Resp); Res:=TJSOnObject.Create(['success',false,'message',E.Message,'rows',TJSONArray.Create()]); end; end; end; procedure TRPCPunten.GetIngaveDataExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); Var P,RO : TJSONObject; R : TJSonArray; I,JobID : INteger; // S : TMemoryStream; Row : TJSonData; FID,FJobType,FLN,FLVN : TField; FMemo : TBlobField; begin Res:=Nil; JobID:=(Params as TJSONArray).Integers[0]; RO:=TJSONObject.Create(); Res:=Ro; R:=TJSOnArray.Create(); With QGetIngaveData do begin Close; Params.ParamByName('JobID').AsInteger:=JobID; Open; try FID:=FieldByname('J_ID'); FMemo:=FieldByname('J_MEMO') as TBlobField; FJobTYpe:=FieldByName('J_JOBTYPE'); FLN:=FieldByName('LL_NAAM'); FLVN:=FieldByName('LL_VOORNAAM'); While not EOF do begin if (FJobType.AsInteger<>293) then Raise EWisaWeb.CreateFmt('Job %d bevat geen geldige punteningave gegevens',[JobID]); With TJSONParser.Create(FMemo.AsString) do try Row:=Parse; (Row as TJSONObject).Add('ID',FID.asInteger); (Row as TJSONObject).Add('Leerling',AnsiToUTF8(FLN.AsString+' '+FLVN.asString)); R.Add(row); finally Free; end; Next; end; finally Close; end; end; RO.Add('rows',R); RO.Add('success',True); RO.Add('total',R.Count); // Log('Sending response: '+RO.asJSON); end; procedure TRPCPunten.GetIngaveModelExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); Var JobID : Integer; cols : TJSONData; flds : TJSONData; P : TJSONParser; begin Cols:=Nil; Flds:=Nil; JobID:=(Params as TJSONArray).Integers[0]; With QGetModelData do begin ParamByName('JobID').asInteger:=JObID; Open; try While not EOF do begin P:=TJSONParser.Create(QGetModelData.FieldByName('J_MEMO').AsString); try Case QGetModelData.FieldByName('J_TYPERECORD').AsInteger of 0 : cols:=P.Parse; 1 : flds:=P.Parse; end; finally P.Free; end; Next; end; finally Close; end; end; if (Cols=Nil) or (flds=nil) then Raise Exception.Create('Kon de fields/col data niet laden'); Res:=TJSONObject.Create(['columns',cols,'fields',flds]); // Log('Sending model: '+Res.asJSON); end; procedure TRPCPunten.GetPuntenboekjeInstallVersionExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); begin Res:=TJSONString.Create(WebWisadConfig.PuntenboekjeInstallVersie); end; procedure TRPCPunten.GetPuntenboekListExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); Var A : TJSONArray; O : TJSONObject; FID,FDescr,FNaam,FcreatedOn,FLastMod : TField; begin A:=TJSONArray.Create; Res:=A; With QGetPuntenboekjes do begin Close; ParamByName('K_ID').AsInteger:=GetPuntenboekKastID; ParamByName('PS_ID').AsInteger:=(Session as TWebwisadSession).PSID; Open; try FID:=FieldByName('D_ID'); FDescr:=FieldByName('D_OMSCHRIJVING'); FNaam:=FieldByName('D_NAAM'); FcreatedOn:=FieldByName('D_AANGEMAAKTOP'); FLastMod:=FieldByName('D_LAATSTEWIJZIGING'); While not EOF do begin O:=TJSONObject.Create; A.Add(O); O.Add(FID.FieldName,FID.AsInteger); O.Add(FDescr.FieldName,FDescr.AsString); O.Add(FNaam.FieldName,FNaam.AsString); O.Add(FCreatedOn.FieldName,JSONDate(FCreatedOn.AsDateTime)); O.Add(FLastMod.FieldName,JSONDate(FLastMod.AsDateTime)); Next; end; finally Close; end; end; end; procedure TRPCPunten.GetSyncServerConfigExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); begin Res:=Nil; If (WebWisadConfig.SyncServerURL='') then Raise Exception.Create('Geen synchronisatie server gegevens beschikbaar'); Res:=TJSONObject.Create(['url',WebWisadConfig.SyncServerURL,'database',WebWisadConfig.SyncDatabase]); end; Function TRPCPunten.GetPuntenBoekKastId : Integer; Const PBSelect = 'SELECT K_ID FROM KAST WHERE (K_CODE=''PUNTB'')'; Var Q : TWisaWebQuery; begin if (WebWisadConfig.PuntenBoekKastID=0) then begin Q:=DatabaseManager.GetQuery(Self,PBSelect,Database,Nil); try Q.open; if (Q.EOF and Q.BOF) then WebWisadConfig.PuntenBoekKastID:=-1 else WebWisadConfig.PuntenBoekKastID:=Q.FieldByName('K_ID').AsInteger finally Q.Free; end; end; Result:=WebWisadConfig.PuntenBoekKastID; Log('Puntenboek kast id : %d',[Result]); end; procedure TRPCPunten.PreparePuntenboekForDownloadExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); Var ID : Integer; begin Res:=Nil; ID:=Params.Items[0].AsInteger; With QGetKastPSFromDocument do begin Close; ParamByname('D_ID').AsInteger:=ID; Open; try If (EOF and BOF) then Raise EWIsaWeb.CreateFmt('%d is geen geldig documentnummer',[ID]); If (FieldByname('D_KAST_FK').AsInteger<>GetPuntenBoekKastID) then Raise EWIsaWeb.CreateFmt('%d is geen puntenboek document',[ID]); If (FieldByname('D_BRON_FK').AsInteger<>(Session as TWebWisadSession).PSID) then Raise EWIsaWeb.CreateFmt('%d is geen puntenboek van personeelslid %s',[ID,Session.FullName]); Session.AddDocumentID(ID); Res:=TJSONBoolean.Create(True); finally Close; end; end; end; procedure TRPCPunten.UpdateMemo(S : string; MID : Integer); begin With QUpdateMemo do begin ParamByName('ID').AsInteger:=MID; ParamByName('UID').AsInteger:=UserID; ParamByName('BM_MEMO').AsString:=S; ExecSQL; end; end; procedure TRPCPunten.UpdateMemoPointer(JID,MID : Integer); begin With QUpdateMemoPointer do begin ParamByName('ID').AsInteger:=JID; If (MID=-1) then ParamByName('MemoID').Clear else ParamByName('MemoID').AsInteger:=MID; ExecSQL; end; end; procedure TRPCPunten.DeleteMemo(ID : Integer) ; begin With QDeleteMemo do begin ParamByName('ID').AsInteger:=ID; ExecSQL; end; end; function TRPCPunten.InsertMemo(S : String; LBID : Integer) : Integer; begin With QInsertMemo do begin Result:=Gen_ID('GEN_LOOPBAANMEMO'); ParamByName('BM_ID').AsInteger:=Result; ParamByName('BM_MEMO').AsString:=S; ParamByName('BM_LOOPBAAN_FK').AsInteger:=LBID; ParamByName('UID').AsINteger:=UserID; ExecSQL; end; end; procedure TRPCPunten.GetMemoTypeIDandComment(JobId : Integer); begin With QGetMTAndOpmerking do begin Close; ParamByName('JobID').AsInteger:=JObID; Open; try if (EOF and BOF) then Raise Exception.Create('Kon de omschrijving en type memo ID niet ophalen'); QInsertMemo.ParamByName('BM_OMSCHRIJVING').AsString:=FieldByName('J_LONGTEXT1').AsString; QInsertMemo.ParamByName('BM_TYPE_FKP').AsInteger:=FieldByName('J_INTEGER1').AsInteger; finally Close; end; end; end; procedure TRPCPunten.ProcessCommentsExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); Var J_ID, J_INTEGER1, J_INTEGER2, J_MEMO : TField; JobID,ID : Integer; S,OPm : String; begin Res:=Nil; JobID:=(Params as TJSONArray).Integers[0]; Session.CheckJobID(JobID); GetMemoTypeIDAndComment(JobID); With QGetModifiedMemos do begin Close; ParamByName('JOBID').AsInteger:=JobID; Open; try J_ID:=FieldByname('J_ID'); J_INTEGER1:=FieldByname('J_INTEGER1'); J_INTEGER2:=FieldByname('J_INTEGER2'); J_MEMO:=FieldByname('J_MEMO'); While not EOF do begin If J_INTEGER2.IsNull then begin S:=J_MEMO.AsString; If (S<>'') then begin ID:=InsertMemo(S,J_INTEGER1.AsInteger); UpdateMemoPointer(J_ID.AsInteger,ID); end; end else begin S:=J_MEMO.AsString; If (S<>'') then UpdateMemo(S,J_INTEGER2.AsInteger) else begin DeleteMemo(J_INTEGER2.AsInteger); UpdateMemoPointer(J_ID.AsInteger,-1); end; end; Next; end; finally Close; end; end; Transaction.Commit; Res:=TJSONBoolean.Create(true); end; procedure TRPCPunten.MergePunt(PD : TPeriodeData; PP : TIngavePunt; Opm : TVakOpmerking; D : TJSONData); Var s,ds : String; t : TJSONType; begin t:=D.JSONType; if (t<>jtNull) then ds:=D.AsString; case t of jtNull: If (Opm<>Nil) then Opm.Opmerking:='' else PP.Punt:=-1; jtString : if (Opm<>Nil) then Opm.Opmerking:=UTF8ToAnsi(ds) else if ds='' then PP.Punt:=-1 else PP.Punt:=StringToPuntEx(DS,PD.Schaal,2,PD.lijst); jtNumber : If (Opm<>Nil) then Opm.Opmerking:=UTF8ToAnsi(ds) else PP.Punt:=Round(D.AsFloat*100); else Raise Exception.Create('Invalid data type for punt '+ds); end; end; Function TRPCPunten.GetPeriodePunt(LL : TIngavePuntenGroepItem; Const ColName : String; Out PID : Integer; Out Opm : TVakOpmerking) : TIngavePunt; Var N : String; P, VID : Integer; VP: TIngaveVakpuntenItem; begin Result:=Nil; N:=lowercase(ColName); if Copy(N,1,6)='kolom_' then begin Delete(N,1,6); P:=Pos('_',N); VID:=StrToIntDef(Copy(N,1,P-1),-1); Delete(N,1,P); P:=Pos('_opm',N); VP:=LL.VakPunten.FindVakByID(VID); If (VP=Nil) then Raise Exception.CreateFmt('%s met vak ID %d is geen geldig vak',[ColName,VID]); If (P=0) then begin PID:=StrToIntDef(N,-1); opm:=nil end else begin PID:=StrToIntDef(Copy(N,1,P-1),-1); Opm:=VP.Opmerkingen.FindPeriodeOpmerking(PID); If Opm=Nil then begin Opm:=VP.Opmerkingen.AddOpmerking; Opm.PeriodeID:=PID; end; end; Result:=VP.PeriodePunten.FindPeriodeByID(PID); If (Result=Nil) then Raise Exception.CreateFmt('%s met periode ID %d is geen geldige periode',[ColName,PID]); end end; Function TRPCPunten.GetPeriodeData(PID : Integer) : TPeriodeData; begin With QGetPeriodeData do begin Close; ParamByName('PE_ID').AsInteger:=PID; Open; try if (EOF and BOF) then Raise Exception.CreateFmt('Periode %d is geen geldig periode ID',[PID]); Result:=TPeriodeData.Create; LoadPeriodeData(Result,QGetPeriodeData); finally Close; end; end; end; procedure TRPCPunten.MergeIngavePunten(Data : TIDList; Groep : TIngavePuntenGroep); Var LL : TIngavePuntenGroepItem; I,J,P,VID,PID : Integer; D : TJSONObject; N : TJSONStringType; PP : TIngavePunt; Opm : TVakOpmerking; PDS : TIDList; PD : TPeriodeData; begin PDS:=TIDList.Create; try for I:=0 to Data.Count-1 do begin // Log('Merging %d',[Data[i]]); LL:=Groep.FindLeerlingByLBID(Data[i]); D:=Data.Objects[i] as TJSONObject; For J:=0 to D.Count-1 do begin N:=D.Names[J]; PP:=GetPeriodePunt(LL,N,PID,Opm); if (PP<>Nil) then begin P:=PDS.indexOf(PID); if P=-1 then begin PD:=GetPeriodeData(PID); PDS.AddObject(PID,PD); end else PD:=PDS.Objects[p] as TPeriodeData; MergePunt(PD, PP,Opm,D.Items[j]); end; end; end; finally For I:=0 to PDS.Count-1 do PDS.Objects[i].Free; PDS.Free; end; // Log('Done merging'); end; procedure TRPCPunten.SaveIngavePuntenGroep(JID: Integer; Groep : TIngavePuntenGroep); Var T : TStringStream; begin With QUpdateJobData do begin ParamByName('J_ID').AsInteger:=JID; T:=TStringStream.Create(''); try Groep.SaveToStream(T,False); ParamByName('J_MEMO').AsString:=T.DataString; finally T.free; end; ExecSQL; (Transaction as TSQLTransaction).Commit; end; end; procedure TRPCPunten.SchrijfLeerlingPunten(ALBID, PMID, AVakId, AB : Integer); begin // Log('Schrijf punten %d',[ALBID]); With QInsertLeerlingPunten do begin ParamByName('LP_VERANDERDDOOR').AsInteger:=UserID; ParamByName('LP_LOOPBAAN_FK').AsInteger:=ALBID; ParamByName('LP_VAKONDERDEEL_FK').AsInteger:=AVakID; ParamByName('LP_BLOK').AsInteger:=AB; ParamByName('LP_PERIODEMODEL_FK').AsInteger:=PMID; ExecSQL; (Transaction as TSQLTransaction).Commit; end; end; procedure TRPCPunten.WijzigLeerlingPunten(LPID : Integer; P : TPuntenArray; Opmerking : TStringStream); Var I : Integer; begin // Log('Wijzig punten %d',[LPID]); with QUpdateLeerlingPunten do begin prepare; Params.ParamByName('LP_ID').AsInteger := LPID; Params.ParamByName('LP_VeranderdDoor').AsInteger := UserId; For I:=0 to 17 do if P[i] = -1 then Params.ParamByName('LP_Punt'+intToStr(I)).Clear else Params.ParamByName('LP_Punt'+IntToStr(i)).AsInteger := P[i]; if (Opmerking.Size=0) then Params.ParamByName('LP_Opmerking').Clear else Params.ParamByName('LP_Opmerking').AsString := Opmerking.DataString; ExecSql; end; end; procedure TRPCPunten.SaveIngavePunten(JID: Integer; Groep : TIngavePuntenGroep); Var O,T : TStringStream; B,I,J,K,L,LPID : Integer; P : TPuntenArray; begin // Log('Saving punten'); With Groep do for I := 0 to (Count - 1) do With Items[I] as TIngavePuntenGroepItem do begin With Vakpunten do for J := 0 to (Count - 1) do With Items[J] as TIngaveVakPuntenItem do begin ClearPunten(P); B := 0; // minstens blok 0 dient te bestaan O:=TStringStream.Create(''); try LPID:=LeesLeerlingPunten(LBID, VakId, B,P,O); // Log('LPID 1 : %d',[LPID]); if (LPID=-1) then begin SchrijfLeerlingPunten(LBID, Groep.PeriodeModelID, VakId, B); LPID:=LeesLeerlingPunten(LBID, VakId,B,P,O); // Log('LPID 1a : %d',[LPID]); end; Opmerkingen.SaveToStream(O); O.Seek(0,soFromBeginning); // Log('Saving punten %d',[LPID]); With PeriodePunten do begin for K := 0 to (Count - 1) do With Items[K] as TIngavePunt do begin L:=BerekenBlok(Kolom); if L <> B then begin // Log('First %d',[SourceID]); WijzigLeerlingPunten(SourceID,P,O); B := L; // Log('Source 1 : %d',[SourceId]); if (SourceId=-1) then SchrijfLeerlingPunten(LBID, Groep.PeriodeModelID, VakId, B); LPID:=LeesLeerlingPunten(LBID, VakId, B,P,O); // Log('LPID 2 : %d',[LPID]); SourceID:=LPID; // Log('SourceID 2 : %d',[SourceID]); end; L := Kolom mod AantalPeriodes; if L = 0 then L := AantalPeriodes; // Log('Modifying punt %d : %d ',[L,Punt]); If (L>0) and (L<=AantalPeriodes) then P[L-1] := Punt; end; // Log('Second %d',[LPID]); WijzigLeerlingPunten(LPID,P,O); end; finally O.Free; end; end; end; Self.Transaction.Commit; end; procedure TRPCPunten.ProcessJobExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData); Var Data : TIDList; Groep : TIngavePuntenGroep; JobID,I,ACount,GID : Integer; begin JobID:=(Params as TJSONArray).Integers[0]; Groep:=TIngavePuntenGroep.Create; try Data:=TIDList.Create; try With QGetModifiedData do begin ParamByname('JobID').AsInteger:=JobID; Open; try While not EOF do begin If FieldByName('J_TYPERECORD').AsInteger = 3 then begin LoadGroep(JobID,Groep,FieldByName('J_MEMO').AsString); GID:=FieldByName('J_ID').AsInteger; end else With TJSONParser.Create(FieldByName('J_MEMO').AsString) do try // Log('Loading %d',[FieldByName('J_INTEGER1').AsInteger]); Data.AddObject(FieldByName('J_INTEGER1').AsInteger,Parse); finally Free; end; Next; end; finally Close; end; end; ACount:=Data.Count; If (ACount>0) then MergeIngavePunten(Data,Groep); finally For I:=0 to Data.Count-1 do Data.Objects[i].Free; Data.Free; end; If (ACount>0) then SaveIngavePunten(Gid,Groep); finally Groep.Free; end; Res:=TJSONBoolean.Create(true); end; class function TRPCPunten.ActionName: string; begin Result:='WisaPuntenAPI'; end; initialization RegisterWISARPCModule(TRPCPunten); end.