Patch level :
Files correlati : Ricompilazione Demo : [ ] Commento : git-svn-id: svn://10.65.10.50/branches/R_10_00@21585 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
parent
267bce0e34
commit
9960d688a0
13
ha/ha0200a.h
13
ha/ha0200a.h
@ -38,12 +38,13 @@
|
||||
|
||||
//importazione dati
|
||||
#define F_INPUT_PATH 260
|
||||
#define F_IN_TIPODOC_F 261
|
||||
#define F_IN_TIPODOC_B 262
|
||||
#define F_IN_TIPODOC_O 263
|
||||
#define F_IN_TIPODOC_V 264
|
||||
#define F_IN_CODCAUS 265
|
||||
#define F_IN_DESCRCAUS 266
|
||||
#define F_ARCHIVE_PATH 261
|
||||
#define F_IN_TIPODOC_F 262
|
||||
#define F_IN_TIPODOC_B 263
|
||||
#define F_IN_TIPODOC_O 264
|
||||
#define F_IN_TIPODOC_V 265
|
||||
#define F_IN_CODCAUS 266
|
||||
#define F_IN_DESCRCAUS 267
|
||||
|
||||
//comuni inportazione-esportazione
|
||||
#define F_CODICI_IVA 270
|
||||
|
@ -391,14 +391,14 @@ BEGIN
|
||||
FIELD "TipoBarcode"
|
||||
END
|
||||
|
||||
GROUPBOX DLG_NULL 76 14
|
||||
GROUPBOX DLG_NULL 76 15
|
||||
BEGIN
|
||||
PROMPT 1 8 "@bImportazione"
|
||||
END
|
||||
|
||||
STRING F_INPUT_PATH 255 44
|
||||
STRING F_INPUT_PATH 255 43
|
||||
BEGIN
|
||||
PROMPT 2 9 "Percorso files da importare "
|
||||
PROMPT 2 9 "Percorso files da importare "
|
||||
DSELECT
|
||||
FLAGS "M"
|
||||
CHECKTYPE REQUIRED
|
||||
@ -406,14 +406,24 @@ BEGIN
|
||||
FIELD InputPath
|
||||
END
|
||||
|
||||
STRING F_ARCHIVE_PATH 255 43
|
||||
BEGIN
|
||||
PROMPT 2 10 "Percorso files da archiviare "
|
||||
DSELECT
|
||||
FLAGS "M"
|
||||
CHECKTYPE REQUIRED
|
||||
WARNING "Selezionare una cartella valida!"
|
||||
FIELD ArchivePath
|
||||
END
|
||||
|
||||
TEXT DLG_NULL
|
||||
BEGIN
|
||||
PROMPT 2 10 "@bTipi documento generati in importazione"
|
||||
PROMPT 2 11 "@bTipi documento generati in importazione"
|
||||
END
|
||||
|
||||
STRING F_IN_TIPODOC_F 4
|
||||
BEGIN
|
||||
PROMPT 2 11 "Fatture "
|
||||
PROMPT 2 12 "Fatture "
|
||||
USE %TIP
|
||||
INPUT CODTAB F_IN_TIPODOC_F
|
||||
DISPLAY "Codice@8" CODTAB
|
||||
@ -425,7 +435,7 @@ END
|
||||
|
||||
STRING F_IN_TIPODOC_B 4
|
||||
BEGIN
|
||||
PROMPT 18 11 "Bolle "
|
||||
PROMPT 18 12 "Bolle "
|
||||
USE %TIP
|
||||
INPUT CODTAB F_IN_TIPODOC_B
|
||||
DISPLAY "Codice@8" CODTAB
|
||||
@ -437,7 +447,7 @@ END
|
||||
|
||||
STRING F_IN_TIPODOC_O 4
|
||||
BEGIN
|
||||
PROMPT 34 11 "Ordini "
|
||||
PROMPT 34 12 "Ordini "
|
||||
USE %TIP
|
||||
INPUT CODTAB F_IN_TIPODOC_O
|
||||
DISPLAY "Codice@8" CODTAB
|
||||
@ -449,7 +459,7 @@ END
|
||||
|
||||
STRING F_IN_TIPODOC_V 4
|
||||
BEGIN
|
||||
PROMPT 50 11 "Bolle valorizz. "
|
||||
PROMPT 50 12 "Bolle valorizz. "
|
||||
USE %TIP
|
||||
INPUT CODTAB F_IN_TIPODOC_V
|
||||
DISPLAY "Codice@8" CODTAB
|
||||
@ -461,17 +471,17 @@ END
|
||||
|
||||
TEXT DLG_NULL
|
||||
BEGIN
|
||||
PROMPT 2 12 "Le numerazioni sono generate automaticamente in base al tipo documento ricevuto"
|
||||
PROMPT 2 13 "Le numerazioni sono generate automaticamente in base al tipo documento ricevuto"
|
||||
END
|
||||
|
||||
TEXT DLG_NULL
|
||||
BEGIN
|
||||
PROMPT 2 13 "ed al codice terminale, secondo la regola: 'TipoDocumento'+'CodiceTerminale. Es. 'F'+'001' -> F001"
|
||||
PROMPT 2 14 "ed al codice terminale, secondo la regola: 'TipoDocumento'+'CodiceTerminale. Es. 'F'+'001' -> F001"
|
||||
END
|
||||
|
||||
STRING F_IN_CODCAUS 3
|
||||
BEGIN
|
||||
PROMPT 2 14 "Causale movimenti da incassi "
|
||||
PROMPT 2 15 "Causale movimenti da incassi "
|
||||
FLAGS "UZ"
|
||||
USE LF_CAUSALI
|
||||
INPUT CODCAUS F_IN_CODCAUS
|
||||
@ -485,7 +495,7 @@ END
|
||||
|
||||
STRING F_IN_DESCRCAUS 50 37
|
||||
BEGIN
|
||||
PROMPT 37 14 ""
|
||||
PROMPT 37 15 ""
|
||||
USE LF_CAUSALI KEY 2
|
||||
INPUT DESCR F_IN_DESCRCAUS
|
||||
DISPLAY "Descrizione @50" DESCR
|
||||
@ -496,12 +506,12 @@ END
|
||||
|
||||
TEXT DLG_NULL
|
||||
BEGIN
|
||||
PROMPT 2 16 "@bCodici IVA Campo da utilizzare in base alle aliquote"
|
||||
PROMPT 2 17 "@bCodici IVA Campo da utilizzare in base alle aliquote"
|
||||
END
|
||||
|
||||
SPREADSHEET F_CODICI_IVA 74 4
|
||||
BEGIN
|
||||
PROMPT 2 17 ""
|
||||
PROMPT 2 18 ""
|
||||
ITEM "%IVA@6"
|
||||
ITEM "Cod.IVA"
|
||||
ITEM "Descrizione"
|
||||
|
242
ha/ha1300.cpp
242
ha/ha1300.cpp
@ -2,6 +2,7 @@
|
||||
#include <automask.h>
|
||||
#include <progind.h>
|
||||
#include <reputils.h>
|
||||
#include <utility.h>
|
||||
|
||||
#include "../cg/cg2101.h"
|
||||
#include "../cg/cg2103.h"
|
||||
@ -13,8 +14,6 @@
|
||||
#include "ha1300a.h"
|
||||
#include "ha1301a.h"
|
||||
|
||||
#define UPLOAD_FILE "upload.d"
|
||||
|
||||
|
||||
//funzione di ordinamento del file di upload una volta caricato in memoria
|
||||
|
||||
@ -254,8 +253,10 @@ bool TUpload2Campo_mask::on_field_event(TOperable_field& o, TField_event e, long
|
||||
TUpload2Campo_mask::TUpload2Campo_mask() : TAutomask ("ha1300a")
|
||||
{
|
||||
TConfig config(CONFIG_DITTA, "ha");
|
||||
const TString& path = config.get("InputPath");
|
||||
set(F_PATH, path);
|
||||
const TString& input_path = config.get("InputPath");
|
||||
set(F_INPUT_PATH, input_path);
|
||||
const TString& archive_path = config.get("ArchivePath");
|
||||
set(F_ARCHIVE_PATH, archive_path);
|
||||
}
|
||||
|
||||
|
||||
@ -285,7 +286,6 @@ TUpload2Campo_newcli_mask::TUpload2Campo_newcli_mask() : TAutomask ("ha1301a")
|
||||
///////////////////////////////////////
|
||||
class TUpload2Campo : public TSkeleton_application
|
||||
{
|
||||
TFilename _intput_dir;
|
||||
bool _can_write;
|
||||
TAssoc_array _nuovi_clienti;
|
||||
|
||||
@ -297,9 +297,10 @@ protected:
|
||||
void check_magazzino(const TString& codmag_age, TLog_report& log);
|
||||
void check_causale(TString& codcaus, TLog_report& log);
|
||||
bool genera_incasso(TPartita& game, int nriga, int nrata, const TMovimentoPN& mov, TLog_report& log) const;
|
||||
bool archivia_file_importato(const TString& dst_root_path, const TFilename& curr_fname, const TString& terminalino, TLog_report& log);
|
||||
|
||||
//metodi di alto livello
|
||||
void elabora_SU(THardy_upload_recordset& recset, TLog_report& log);
|
||||
const TString4 elabora_SU(THardy_upload_recordset& recset, TLog_report& log);
|
||||
void elabora_BR(THardy_upload_recordset& recset, TLog_report& log);
|
||||
void elabora_VC(THardy_upload_recordset& recset, TLog_report& log);
|
||||
void elabora_TF(THardy_upload_recordset& recset, TLog_report& log);
|
||||
@ -317,6 +318,58 @@ public:
|
||||
// Metodi di basso livello
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TUpload2Campo::archivia_file_importato(const TString& dst_root_path, const TFilename& curr_fname, const TString& terminalino, TLog_report& log)
|
||||
{
|
||||
//controllo della cartella di destinazione
|
||||
TFilename dst_file = dst_root_path;
|
||||
dst_file.add(terminalino);
|
||||
const bool crea_dir = make_dir(dst_file);
|
||||
//non riesce a crearla/trovarla! deve dare errore di grave livello!
|
||||
if (!crea_dir)
|
||||
{
|
||||
TString msg;
|
||||
msg.format("Impossibile creare la cartella %s !", dst_file);
|
||||
log.log(2, msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
//se invece crea/trova la cartella -> copia il file
|
||||
dst_file.add(curr_fname.name());
|
||||
|
||||
const bool copia_riuscita = fcopy(curr_fname, dst_file);
|
||||
if (!copia_riuscita)
|
||||
{
|
||||
TString msg;
|
||||
msg.format("Impossibile copiare il file %s !", curr_fname.name());
|
||||
log.log(2, msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
//controllo dell'avvenuta copia e della correttezza del file destinazione
|
||||
//controllo sulle dimensioni
|
||||
const long src_size = fsize(curr_fname);
|
||||
const long dst_size = fsize(dst_file);
|
||||
|
||||
if (src_size != dst_size)
|
||||
{
|
||||
TString msg;
|
||||
msg.format("Copia del file %s non completata !", curr_fname.name());
|
||||
log.log(2, msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
//eliminazione del file sorgente
|
||||
const bool src_file_removed = remove_file(curr_fname);
|
||||
if (!src_file_removed)
|
||||
{
|
||||
TString msg;
|
||||
msg.format("Impossibile eliminare il file origine %s ", curr_fname.name());
|
||||
log.log(1, msg);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//controlla se il terminale corrisponde ad un agente registrato e restituisce l'agente
|
||||
const TString& TUpload2Campo::check_agente(TString& codice_terminale, TLog_report& log)
|
||||
{
|
||||
@ -453,8 +506,11 @@ bool TUpload2Campo::genera_incasso(TPartita& game, int nriga, int nrata,
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//SU non è un tipo record di qualche utilità
|
||||
void TUpload2Campo::elabora_SU(THardy_upload_recordset& recset, TLog_report& log)
|
||||
const TString4 TUpload2Campo::elabora_SU(THardy_upload_recordset& recset, TLog_report& log)
|
||||
{
|
||||
TString4 codice_terminale = recset.get("CodiceTerminale").as_string();
|
||||
codice_terminale.format("%03d", atoi(codice_terminale));
|
||||
return codice_terminale;
|
||||
}
|
||||
|
||||
//elabora clienti e loro variazioni; viene comunque eseguita per prima perchè i record VC vengono messi all'inizio
|
||||
@ -621,7 +677,6 @@ void TUpload2Campo::elabora_VC(THardy_upload_recordset& recset, TLog_report& log
|
||||
log.log(2, msg);
|
||||
}
|
||||
}
|
||||
log.log(0, "");
|
||||
}
|
||||
|
||||
//movimenti di incasso
|
||||
@ -788,8 +843,6 @@ void TUpload2Campo::elabora_SI(THardy_upload_recordset& recset, TLog_report& log
|
||||
log.log(2, mov_msg);
|
||||
}
|
||||
} //if(_can_write)...
|
||||
|
||||
log.log(0, "");
|
||||
}
|
||||
|
||||
|
||||
@ -895,8 +948,6 @@ void TUpload2Campo::elabora_BR(THardy_upload_recordset& recset, TLog_report& log
|
||||
msg.insert("Controllato mov. magazzino: ", 0);
|
||||
log.log(0, msg);
|
||||
}
|
||||
|
||||
log.log(0, "");
|
||||
}
|
||||
|
||||
|
||||
@ -1104,8 +1155,6 @@ void TUpload2Campo::elabora_TF(THardy_upload_recordset& recset, TLog_report& log
|
||||
msg.insert("Controllato documento: ", 0);
|
||||
log.log(0, msg);
|
||||
}
|
||||
|
||||
log.log(0, "");
|
||||
}
|
||||
|
||||
|
||||
@ -1213,86 +1262,128 @@ void TUpload2Campo::elabora_RC(THardy_upload_recordset& recset, TLog_report& log
|
||||
msg.insert("Controllato documento di carico: ", 0);
|
||||
log.log(0, msg);
|
||||
}
|
||||
|
||||
log.log(0, "");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void TUpload2Campo::elabora(const TMask& mask)
|
||||
{
|
||||
//creazione del filename del file da importare
|
||||
TFilename src_file = mask.get(F_PATH);
|
||||
src_file.add(UPLOAD_FILE);
|
||||
//prende la directory di archiviazione
|
||||
const TString archive_path = mask.get(F_ARCHIVE_PATH);
|
||||
|
||||
THardy_upload_recordset recset(src_file);
|
||||
const long items = recset.items();
|
||||
//ordinamento del file in memoria; sotto ogni TF (testata) mette le sue righe (RF)...MAGIA!!!
|
||||
recset.sort(ordina_upload);
|
||||
//creazione del filename dei files da importare
|
||||
TFilename src_files = mask.get(F_INPUT_PATH);
|
||||
//si importano tutti i files di tipo upload*.d
|
||||
src_files.add("upload*.d");
|
||||
TString_array src_files_list;
|
||||
const int n_files_d = list_files(src_files, src_files_list);
|
||||
|
||||
#ifdef DBG
|
||||
recset.save_as("D:/dati/hardy/cazzone.txt");
|
||||
#endif
|
||||
|
||||
//creazione progind e log
|
||||
TProgind pi(items, TR("Acquisizione dati in corso..."), true, true);
|
||||
TProgind pi(n_files_d, TR("Acquisizione files in corso..."), true, true);
|
||||
TLog_report log("Segnalazioni su acquisizione");
|
||||
log.kill_duplicates();
|
||||
log.log(0, "");
|
||||
|
||||
//parametro di controllo; solo se resta true fino alla fine il documento viene writato
|
||||
//solo in caso di elaborazione definitiva può diventare true
|
||||
_can_write = false;
|
||||
if (mask.get_bool(F_DEFINITIVO))
|
||||
_can_write = true;
|
||||
|
||||
//giro su tutti i record del terribile recordset per l'acquisizione dei dati
|
||||
for (bool ok = recset.move_first(); ok; ok = recset.move_next())
|
||||
//scandisce i files uno ad uno
|
||||
for (int i = 0; i < n_files_d; i++)
|
||||
{
|
||||
if (!pi.addstatus(1))
|
||||
break;
|
||||
//file corrente in fase di elaborazione
|
||||
const TFilename curr_fname = src_files_list.row(i);
|
||||
|
||||
//acquisizione tipo record da riga corrente del file di input
|
||||
TString4 tipo_record = recset.rec_type();
|
||||
tipo_record.trim();
|
||||
THardy_upload_recordset recset(curr_fname);
|
||||
const long items = recset.items();
|
||||
//ordinamento del file in memoria secondo l'ordine stabilito nella tipi_record "SU|VC|TF|RF|SI|BR|RC";
|
||||
recset.sort(ordina_upload);
|
||||
|
||||
//Sequenza di ordinamento dei record "SU|VC|TF|RF|SI|BR|RC": NON ATTENTATEVI A CAMBIARLA O NON FUNZIONA PIU' UN CAZZO!!
|
||||
const int pos = tipi_record.get_pos(tipo_record);
|
||||
|
||||
//trattazione dei vari tracciati record
|
||||
switch (pos)
|
||||
TString msg;
|
||||
#ifdef DBG
|
||||
msg << "D:/dati/hardy/" << "cazzone_" << curr_fname.name_only() << ".txt";
|
||||
recset.save_as(msg);
|
||||
#endif
|
||||
|
||||
//creazione progind e log
|
||||
msg.cut(0);
|
||||
msg << "Elaborazione file " << curr_fname << " in corso...";
|
||||
TProgind pi(items, msg, true, true);
|
||||
|
||||
msg.cut(0);
|
||||
msg << "File " << curr_fname.name_only();
|
||||
log.log(0, "");
|
||||
log.log(0, msg);
|
||||
log.log(0, "");
|
||||
//parametro di controllo; solo se resta true fino alla fine il documento viene writato
|
||||
//solo in caso di elaborazione definitiva può diventare true; vale per ogni upload*.d, in modo da archiviare..
|
||||
//..quelli buoni
|
||||
_can_write = false;
|
||||
if (mask.get_bool(F_DEFINITIVO))
|
||||
_can_write = true;
|
||||
|
||||
//codice terminalino; viene preso dal tipo record SU (è comunque presente in ogni tipo record) ed usato per l'archiviazione..
|
||||
//..del file se correttamente importato
|
||||
TString4 terminalino;
|
||||
|
||||
//giro su tutti i record del terribile recordset per l'acquisizione dei dati
|
||||
for (bool ok = recset.move_first(); ok; ok = recset.move_next())
|
||||
{
|
||||
case 0: //tipo record: SU (SetUp...ovvero agente)
|
||||
//elabora_SU(recset, log); //non serve a una cippa!
|
||||
break;
|
||||
case 1: //tipo record: VC (nuovi clienti e Variazioni Cliente)
|
||||
elabora_VC(recset, log);
|
||||
break;
|
||||
case 2: //tipo record: TF (Testata Fattura)
|
||||
elabora_TF(recset, log);
|
||||
break;
|
||||
case 3: //tipo record: RF (Riga Fattura)
|
||||
//elabora_RF(recset, log); //non serve! lo fa l'elaborazione di testata
|
||||
break;
|
||||
case 4: //tipo record: SI (incasso documenti)
|
||||
elabora_SI(recset, log);
|
||||
break;
|
||||
case 5: //tipo record: BR (righe movimenti magazzino)
|
||||
elabora_BR(recset, log);
|
||||
break;
|
||||
case 6: //tipo record: RC (Richiesta Carico)
|
||||
elabora_RC(recset, log);
|
||||
break;
|
||||
default: //se il tipo record non esiste nella lista dei tipi record si incazza e lo scrive!
|
||||
{
|
||||
TString msg;
|
||||
msg << "Tipo record non riconosciuto '" << tipo_record << "' alla riga " << (recset.current_row() + 1);
|
||||
log.log(2, msg);
|
||||
}
|
||||
break;
|
||||
} //switch(pos)..
|
||||
if (!pi.addstatus(1))
|
||||
break;
|
||||
|
||||
} //for (bool ok...
|
||||
//acquisizione tipo record da riga corrente del file di input
|
||||
TString4 tipo_record = recset.rec_type();
|
||||
tipo_record.trim();
|
||||
|
||||
//Sequenza di ordinamento dei record "SU|VC|TF|RF|SI|BR|RC": NON ATTENTATEVI A CAMBIARLA O NON FUNZIONA PIU' UN CAZZO!!
|
||||
const int pos = tipi_record.get_pos(tipo_record);
|
||||
|
||||
//trattazione dei vari tracciati record
|
||||
switch (pos)
|
||||
{
|
||||
case 0: //tipo record: SU (SetUp...ovvero agente)
|
||||
terminalino = elabora_SU(recset, log); //non serve a una cippa!
|
||||
break;
|
||||
case 1: //tipo record: VC (nuovi clienti e Variazioni Cliente)
|
||||
elabora_VC(recset, log);
|
||||
break;
|
||||
case 2: //tipo record: TF (Testata Fattura)
|
||||
elabora_TF(recset, log);
|
||||
break;
|
||||
case 3: //tipo record: RF (Riga Fattura)
|
||||
//elabora_RF(recset, log); //non serve! lo fa l'elaborazione di testata
|
||||
break;
|
||||
case 4: //tipo record: SI (incasso documenti)
|
||||
elabora_SI(recset, log);
|
||||
break;
|
||||
case 5: //tipo record: BR (righe movimenti magazzino)
|
||||
elabora_BR(recset, log);
|
||||
break;
|
||||
case 6: //tipo record: RC (Richiesta Carico)
|
||||
elabora_RC(recset, log);
|
||||
break;
|
||||
default: //se il tipo record non esiste nella lista dei tipi record si incazza e lo scrive!
|
||||
{
|
||||
TString msg;
|
||||
msg << "Tipo record non riconosciuto '" << tipo_record << "' alla riga " << (recset.current_row() + 1);
|
||||
log.log(2, msg);
|
||||
}
|
||||
break;
|
||||
} //switch(pos)..
|
||||
|
||||
} //for (bool ok... (acquisizione di un file)
|
||||
log.log(0, "");
|
||||
|
||||
//sequenza di archiviazione del file di upload se elaborato con successo in via definitiva
|
||||
if (_can_write)
|
||||
{
|
||||
if (archivia_file_importato(archive_path, curr_fname, terminalino, log))
|
||||
{
|
||||
msg.cut(0);
|
||||
msg << "Archiviato file " << curr_fname.name_only();
|
||||
log.log(0, msg);
|
||||
}
|
||||
}
|
||||
|
||||
} //for (int i = 0; i < n_files_d;... (giro su tutti i files tipo upload*.d)
|
||||
|
||||
log.preview();
|
||||
}
|
||||
@ -1301,7 +1392,6 @@ void TUpload2Campo::elabora(const TMask& mask)
|
||||
void TUpload2Campo::main_loop()
|
||||
{
|
||||
TUpload2Campo_mask mask;
|
||||
_intput_dir = mask.get(F_PATH);
|
||||
while (mask.run() == K_ENTER)
|
||||
{
|
||||
elabora(mask);
|
||||
|
@ -1,2 +1,3 @@
|
||||
#define F_PATH 201
|
||||
#define F_DEFINITIVO 202
|
||||
#define F_INPUT_PATH 201
|
||||
#define F_ARCHIVE_PATH 202
|
||||
#define F_DEFINITIVO 203
|
@ -1,16 +1,22 @@
|
||||
#include "ha1300a.h"
|
||||
|
||||
PAGE "Importazione dati da file upload" -1 -1 78 5
|
||||
PAGE "Importazione dati da file upload" -1 -1 78 6
|
||||
|
||||
STRING F_PATH 256 45
|
||||
STRING F_INPUT_PATH 256 45
|
||||
BEGIN
|
||||
PROMPT 1 1 "Cartella file da importare "
|
||||
FLAGS "D"
|
||||
END
|
||||
|
||||
STRING F_ARCHIVE_PATH 256 45
|
||||
BEGIN
|
||||
PROMPT 1 2 "Cartella di archiviazione "
|
||||
FLAGS "D"
|
||||
END
|
||||
|
||||
BOOLEAN F_DEFINITIVO
|
||||
BEGIN
|
||||
PROMPT 1 3 "Elaborazione definitiva (scrittura sul database)"
|
||||
PROMPT 1 4 "Elaborazione definitiva (scrittura sul database)"
|
||||
END
|
||||
|
||||
ENDPAGE
|
||||
|
Loading…
x
Reference in New Issue
Block a user