diff --git a/ca/ca3700.cpp b/ca/ca3700.cpp index a23ac5d6a..6078a3123 100755 --- a/ca/ca3700.cpp +++ b/ca/ca3700.cpp @@ -2,6 +2,9 @@ #include #include #include +#include +#include +#include "../ve/velib04.h" #include "pconana.h" #include "movana.h" @@ -32,8 +35,6 @@ const TString& TPrint_rendiconto_ca_mask::get_report_class() const { TString& classe = get_tmp_string(); classe = "ca3700a"; -// const int stp = get_int(F_TIPOCONTI); -// classe << (stp == 1 ? 'a' : 'b'); // tipo di report da usare in caso di report multipli return classe; } @@ -219,11 +220,13 @@ TPrint_rendiconto_ca_mask::TPrint_rendiconto_ca_mask() /////////////////////////////////////////////////////////////// -// RECORDSET PRINCIPALE (caso standard: conti movimentati) +// RECORDSET /////////////////////////////////////////////////////////////// class TPrint_rendiconto_ca_recordset : public TISAM_recordset { + TExternisamfile* _tmp; + protected: int _anno; int _tipoconti; @@ -239,13 +242,21 @@ protected: static bool mov_filter(const TRelation* rel); bool valid_record(const TRelation& rel) const; virtual void set_custom_filter(TCursor& cur) const; - const TImporto& saldo_iniziale(const char* conto) const; + + void crea_righe_rmovana(); + void crea_righe_rdoc(const TPrint_rendiconto_ca_mask& msk); + void crea_trr(const TFilename& trr) const; + void salva_rmovana(const TRectype& rmovana, const TRectype& movana); + public: virtual void set_filter(const TPrint_rendiconto_ca_mask& msk, int cms_row); - TPrint_rendiconto_ca_recordset(const TString& sql) : TISAM_recordset(sql) { } + + TPrint_rendiconto_ca_recordset(const TString& sql) : TISAM_recordset(sql) { _tmp = NULL;} + ~TPrint_rendiconto_ca_recordset() { delete _tmp; } }; + static const TPrint_rendiconto_ca_recordset* myself = NULL; //metodo per riconoscere se il record corrente soddisfa i filtri della maschera...strafighissimo! @@ -309,29 +320,9 @@ void TPrint_rendiconto_ca_recordset::set_custom_filter(TCursor& cur) const cur.set_filterfunction(mov_filter, true); } -const TImporto& TPrint_rendiconto_ca_recordset::saldo_iniziale(const char* conto) const -{ - TAnal_bill bill(conto, _codcosto, _codcms, _codfas); - const TSaldanal& saldo = ca_saldo(bill, _dadata, _adata, _tipimov); - return saldo._ini; -} - const TVariant& TPrint_rendiconto_ca_recordset::get(const char* column_name) const { - if (strncmp(column_name, "SALDOINI:", 9) == 0) - { - const TString16 sub_field = column_name+9; - const TString& conto = get(RMOVANA_CODCONTO).as_string(); - const TImporto& saldo_ini = saldo_iniziale(conto); - - TVariant& var = get_tmp_var(); - if (sub_field == "DARE") - var = saldo_ini.sezione() == 'D' ? saldo_ini.valore() : ZERO; - else - var = saldo_ini.sezione() == 'A' ? saldo_ini.valore() : ZERO; - return var; - } if (strcmp(column_name, "#COSTO") == 0) { @@ -354,81 +345,192 @@ const TVariant& TPrint_rendiconto_ca_recordset::get(const char* column_name) con return TISAM_recordset::get(column_name); } -//metodo per caricare i valori nel recordset dalla maschera...fighissimo!! -void TPrint_rendiconto_ca_recordset::set_filter(const TPrint_rendiconto_ca_mask& msk, int cms_row) +void TPrint_rendiconto_ca_recordset::salva_rmovana(const TRectype& rmovana, const TRectype& movana) { - _daconto, _aconto, _codcosto = _codcms = _codfas = ""; - if (cms_row >= 0) - { - TSheet_field& sf = msk.sfield(F_RIGHE); - TMask& sm = sf.sheet_mask(); - sf.update_mask(cms_row); - TRelation rel(LF_RMOVANA); - sm.autosave(rel); - _codcosto = rel.curr().get(RMOVANA_CODCCOSTO); - _codcms = rel.curr().get(RMOVANA_CODCMS); - _codfas = rel.curr().get(RMOVANA_CODFASE); - } - - for (int i = 0; msk.id2pos(F_CDC1_INI+i) > 0; i++) + //tipo movimento CONSUNTIVO + const char tipomov = movana.get_char(MOVANA_TIPOMOV); + if (tipomov <= ' ') { - _daconto << msk.get(F_CDC1_INI+i); - _aconto << msk.get(F_CDC1_FIN+i); + //scegli i campi da mettere + _tmp->curr().put("CONTO", rmovana.get(RMOVANA_CODCONTO)); //conto + _tmp->curr().put("DCODNUM", movana.get(MOVANA_DCODNUM)); //codnum del documento che origina il movana + _tmp->curr().put("DATAREG", movana.get(MOVANA_DATAREG)); //data del movana + _tmp->curr().put("NUMREG", movana.get(MOVANA_NUMREG)); + _tmp->curr().put("NUMDOCRIF", movana.get(MOVANA_DNDOC)); + _tmp->curr().put("DATADOCRIF", movana.get(MOVANA_DATADOC)); + _tmp->curr().put("DESC", movana.get(MOVANA_DESCR)); //??veramente non si sa?? + _tmp->curr().put("NRIGA", rmovana.get(RMOVANA_NUMRIG)); + _tmp->curr().put("DESCRIGA", movana.get(RMOVANA_DESCR)); + _tmp->curr().put("DANDOC", movana.get(MOVANA_DNDOC)); + + //qui ci vuole l'algoritmo di calcolo di fatturato/maturato/impegnato in base al TIPODOC + //o al CODNUM (***quale campo non si sa di preciso***) + const TString4 tipodoc = movana.get(MOVANA_TIPODOC); + +/* _tmp->curr().put("FATTURATO", movana.get(MOVANA_)); + _tmp->curr().put("MATURATO", movana.get(MOVANA_)); + _tmp->curr().put("IMPEGNATO", movana.get(MOVANA_));*/ + + _tmp->write(); // aggiunge i record al file temporaneo + } +} + + +void TPrint_rendiconto_ca_recordset::crea_righe_rmovana() +{ + + TRelation rel_rmovana(LF_RMOVANA); + rel_rmovana.add(LF_MOVANA, "NUMREG==NUMREG"); //aggiunge le testate x avere tipi mov e descr + + //..crea un cursore su rmovana per vedere se i conti selezionati hanno veri movimenti che soddisfano + //i parametri del filtro sulla maschera + TRectype da_rmovana(LF_RMOVANA); + da_rmovana.put(RMOVANA_CODCONTO, _daconto); + da_rmovana.put(RMOVANA_DATACOMP, _dadata); + TRectype a_rmovana(LF_RMOVANA); + a_rmovana.put(RMOVANA_CODCONTO, _aconto); + a_rmovana.put(RMOVANA_DATACOMP, _adata); + + TString filtro; + if (_codcosto.not_empty()) + filtro << "(" << RMOVANA_CODCCOSTO << "==\"" << _codcosto << "\")"; + if (_codcms.not_empty()) + { + if (filtro.not_empty()) + filtro << "&&"; + filtro << "(" << RMOVANA_CODCMS << "==\"" << _codcms << "\")"; + } + if (_codfas.not_empty()) + { + if (filtro.not_empty()) + filtro << "&&"; + filtro << "(" << RMOVANA_CODFASE << "==\"" << _codfas << "\")"; } - _dadata = msk.get_date(F_DATAINI); - _adata = msk.get_date(F_DATAFIN); + TCursor cur_rmovana(&rel_rmovana, filtro, 2, &da_rmovana, &a_rmovana); + const long rmovana_items = cur_rmovana.items(); + cur_rmovana.freeze(); + + if (rmovana_items > 0) + { + const TRectype& rmovana = cur_rmovana.curr(); + const TRectype& movana = rel_rmovana.curr(LF_MOVANA); + for (cur_rmovana = 0; cur_rmovana.pos() < rmovana_items; ++cur_rmovana) + salva_rmovana(rmovana, movana); + } +} + + +void TPrint_rendiconto_ca_recordset::crea_righe_rdoc(const TPrint_rendiconto_ca_mask& msk) +{ + + //scanning del file dei documenti alla ricerca di quelli che hanno la data ed il CODNUM + //validi nei filtri impostati dall'utente + TRelation rel_doc(LF_DOC); +// rel_doc.add(LF_RIGHEDOC, "CODNUM==CODNUM|ANNO==ANNO|PROVV==PROVV|NDOC==NDOC"); //aggiunge le testate + + TRectype dadoc(LF_DOC); + TRectype adoc(LF_DOC); + TString filtro_date; + + dadoc.put(DOC_PROVV, 'D'); + adoc.put(DOC_PROVV, 'D'); + + //se siamo fortunati l'anno si può trovare così.. + int anno = msk.get_int(F_ANNO); + if (anno == 0 && _dadata.year() == _adata.year()) + anno = _adata.year(); + + if (anno > 0) + { + dadoc.put(DOC_ANNO, anno); + adoc.put(DOC_ANNO, anno); + } + + if (_dadata.ok()) + filtro_date << "(ANSI(DATADOC)>=" << _dadata.date2ansi() << ")"; + if (_adata.ok()) + { + if (filtro_date.not_empty()) + filtro_date << "&&"; + + filtro_date << "(ANSI(DATADOC)<=" << _adata.date2ansi() << ")"; + } + + TContabilizzazione_analitica cont_anal; //oggetto necessario per contabilizzare il documento in osservazione + + //deve filtrare per i soli documenti con codnum presente nello sheet dei codnum + TSheet_field& sheet = msk.sfield(F_RIGHE_NUM); + + FOR_EACH_SHEET_ROW(sheet, r, row) + { + const TString4 codnum(row->get(0)); //prende il codice numerazione sulla riga + if (anno > 0) + { + dadoc.put(DOC_CODNUM, codnum); + adoc.put(DOC_CODNUM, codnum); + } + + TString filtro = filtro_date; + if (filtro.not_empty()) + filtro << "&&"; + filtro << "(CODNUM==" << codnum << ")"; + + TCursor cur_doc(&rel_doc, filtro, 1, &dadoc, &adoc); + const long doc_items = cur_doc.items(); + cur_doc.freeze(); + + for (cur_doc = 0; cur_doc.pos() < doc_items; ++cur_doc) + { + TDocumento doc(cur_doc.curr()); + TAnal_mov mov; + cont_anal.elabora(doc, 0, NULL, false, mov); + for (int i = 1; i <= mov.rows(); i++) + salva_rmovana(mov.body()[i], mov); + } + + } } -///////////////////////////////////////////////////////////////////////////////// -// RECORDSET SECONDARIO (casi alternativi: conti con saldo != 0 e tutti i conti) -///////////////////////////////////////////////////////////////////////////////// - -class TPrint_rendiconto_ca_alternative_recordset : public TPrint_rendiconto_ca_recordset +void TPrint_rendiconto_ca_recordset::crea_trr(const TFilename& trr) const { - TIsamtempfile* _tmp_rmovana; -protected: - const TImporto& saldo_finale(const char* conto) const; - virtual void set_custom_filter(TCursor& cur) const; - -public: - virtual void set_filter(const TPrint_rendiconto_ca_mask& msk, int cms_row); - TPrint_rendiconto_ca_alternative_recordset(const TString& sql); - ~TPrint_rendiconto_ca_alternative_recordset() { delete _tmp_rmovana; } -}; - -TPrint_rendiconto_ca_alternative_recordset::TPrint_rendiconto_ca_alternative_recordset(const TString& sql) - : TPrint_rendiconto_ca_recordset(sql) -{ - _tmp_rmovana = NULL; + ofstream of(trr); + of << 1005 << endl; + of << 13 << endl; + of << "CONTO|1|20|0|Conto analitico" << endl; + of << "CODNUM|1|4|0|Numerazione documento" << endl; + of << "DATA|5|8|0|Data movimento o documento" << endl; + of << "NUMREG|3|7|0|Numero registrazione o documento" << endl; + of << "NUMDOCRIF|1|7|0|Numero documento riferimento" << endl; + of << "DATADOCRIF|5|8|0|Data documento riferimento" << endl; + of << "DESC|1|50|0|Descrizione movimento o documento" << endl; + of << "NRIGA|2|3|0|Riga movimento o documento" << endl; + of << "DESCRIGA|1|50|0|Descrizione riga movimento o documento" << endl; + of << "DANDOC|3|7|0|Riferimento ordine/bolla" << endl; + of << "FATTURATO|4|18|5|Fatturato" << endl; + of << "MATURATO|4|18|5|Maturato" << endl; + of << "IMPEGNATO|4|18|5|Impegnato" << endl; + of << 1 << endl; + of << "CONTO+CODNUM+DATA+NUMREG" << endl; } - -const TImporto& TPrint_rendiconto_ca_alternative_recordset::saldo_finale(const char* conto) const +void TPrint_rendiconto_ca_recordset::set_filter(const TPrint_rendiconto_ca_mask& msk, int cms_row) { - TAnal_bill bill(conto, _codcosto, _codcms, _codfas); - const TSaldanal& saldo = ca_saldo(bill, _dadata, _adata, _tipimov); - return saldo._fin; -} + //se esiste il file temporano con tracciato persomalizzato lo cancella e lo ricrea vuoto + TFilename trr; trr.temp(); trr.add("rendiconto.trr"); + TFilename dbf(trr); dbf.ext("dbf"); + + //crea il file .trr in base ai parametri del metodo + crea_trr(trr); -void TPrint_rendiconto_ca_alternative_recordset::set_custom_filter(TCursor& cur) const -{ - //crea un file temporaneo che non viene distrutto ad inizio stampa effettiva - TIsamtempfile* tmp = new TIsamtempfile(LF_RMOVANA, "anal", false, false); - relation()->replace(tmp); //sostituisce il vero file rmovana con quello temporaneo -} + if (_tmp != NULL) + delete _tmp; -void TPrint_rendiconto_ca_alternative_recordset::set_filter(const TPrint_rendiconto_ca_mask& msk, int cms_row) -{ - //se esiste non vuoto il file temporano con tracciato rmovana lo cancella e lo ricrea vuoto - if (_tmp_rmovana != NULL) - delete _tmp_rmovana; + _tmp = new TExternisamfile(dbf, trr); - _tmp_rmovana = new TIsamtempfile(LF_RMOVANA, "anal", true, true); - - //prende un po' di dati dalla maschera + //prende un po' di dati dalla maschera... _daconto, _aconto, _codcosto = _codcms = _codfas = ""; if (cms_row >= 0) { @@ -451,106 +553,10 @@ void TPrint_rendiconto_ca_alternative_recordset::set_filter(const TPrint_rendico _dadata = msk.get_date(F_DATAINI); _adata = msk.get_date(F_DATAFIN); - //scandisce il piano dei conti analitico creando un cursore con i conti nell'intervallo scelto sulla maschera - TRelation rel_pconana(LF_PCONANA); + //metodo per riempire il file + crea_righe_rmovana(); - TRectype daconto(LF_PCONANA); - daconto.put(PCONANA_CODCONTO, _daconto); - TRectype aconto(LF_PCONANA); - aconto.put(PCONANA_CODCONTO, _aconto); - - //solo i gr/co/sottoc completi interessano!!! - - const TMultilevel_code_info& info = ca_multilevel_code_info(LF_PCONANA); - const int min_contolen = info.total_len(-1); - TString filtro; - filtro << "STR(LEN(CODCONTO)>" << min_contolen << ')'; - - TCursor cur_pconana(&rel_pconana, filtro, 1, &daconto, &aconto); - const long pconana_items = cur_pconana.items(); - cur_pconana.freeze(); - TProgind pi(pconana_items, "Scansione conti..."); - - //scandisce il piano dei conti.. - for (cur_pconana = 0; cur_pconana.pos() < pconana_items; ++cur_pconana) - { - pi.addstatus(1); - TRectype& current_pconana_rec = cur_pconana.curr(); - const TString conto = current_pconana_rec.get(PCONANA_CODCONTO); - - bool aggiungi = true; - if (_tipoconti == 2) //se si è scelto di stampare solo quelli con saldo != 0... - { - const TImporto& saldo_fin = saldo_finale(conto); - aggiungi = !saldo_fin.is_zero(); - } - if (aggiungi) //se il conto va aggiunto (casi: conti con saldo !=0 trovato, tutti i conti comunque).. - { - TRelation rel_rmovana(LF_RMOVANA); - rel_rmovana.add(LF_MOVANA, "NUMREG==NUMREG"); //aggiunge le testate x avere i tipi mov. - - //..crea un cursore su rmovana per vedere se i conti selezionati hanno veri movimenti che soddisfano - //i parametri del filtro sulla maschera - TRectype da_rmovana(LF_RMOVANA); - da_rmovana.put(RMOVANA_CODCONTO, conto); - da_rmovana.put(RMOVANA_DATACOMP, _dadata); - TRectype a_rmovana(LF_RMOVANA); - a_rmovana.put(RMOVANA_CODCONTO, conto); - a_rmovana.put(RMOVANA_DATACOMP, _adata); - - TString filtro; - if (_codcosto.not_empty()) - filtro << "(" << RMOVANA_CODCCOSTO << "==\"" << _codcosto << "\")"; - if (_codcms.not_empty()) - { - if (filtro.not_empty()) - filtro << "&&"; - filtro << "(" << RMOVANA_CODCMS << "==\"" << _codcms << "\")"; - } - if (_codfas.not_empty()) - { - if (filtro.not_empty()) - filtro << "&&"; - filtro << "(" << RMOVANA_CODFASE << "==\"" << _codfas << "\")"; - } - - TCursor cur_rmovana(&rel_rmovana, filtro, 2, &da_rmovana, &a_rmovana); - const long rmovana_items = cur_rmovana.items(); - cur_rmovana.freeze(); - bool almeno_uno_aggiunto = false; - if (rmovana_items > 0) - { - for (cur_rmovana = 0; cur_rmovana.pos() < rmovana_items; ++cur_rmovana) - { - //deve coincidere anche il tipomov! sarebbe stato troppo semplice... - const char tipomov = rel_rmovana.curr(LF_MOVANA).get_char(MOVANA_TIPOMOV); - int tipomov_int = 0; - switch (tipomov) - { - case 'P': tipomov_int = 2; break; - case 'V': tipomov_int = 4; break; - default: tipomov_int = 1; break; - } - if ((_tipimov & tipomov_int) != 0) - { - _tmp_rmovana->write(cur_rmovana.curr()); // aggiunge i record al file temporaneo - almeno_uno_aggiunto = true; - } - } - } - //se non ha aggiunto nemmeno un record valido.. - //crea un record di rmovana con il solo conto,datacomp e lo aggiunge al file temporaneo - if (!almeno_uno_aggiunto) - { - TRectype fake_rmovana_rec(LF_RMOVANA); - fake_rmovana_rec.put(RMOVANA_CODCONTO, conto); - fake_rmovana_rec.put(RMOVANA_DATACOMP, _dadata); - _tmp_rmovana->write(fake_rmovana_rec); - } - - } //end if aggiungi - - } //end for su pconana_items + crea_righe_rdoc(msk); } @@ -592,7 +598,7 @@ void TPrint_rendiconto_ca_rep::set_filter(const TPrint_rendiconto_ca_mask& msk, recset = new TPrint_rendiconto_ca_recordset(query); break; default: - recset = new TPrint_rendiconto_ca_alternative_recordset(query); + recset = new TPrint_rendiconto_ca_recordset(query); break; } recset->set_filter(msk, cms_row); @@ -660,4 +666,54 @@ int ca3700(int argc, char* argv[]) TPrint_rendiconto_ca a; a.run(argc, argv, TR("Stampa rendiconto")); return 0; -} \ No newline at end of file +} + +/* +//Prototipi di metodi di calcolo (ricordarsi di usare come importi quelli di riga) +COMM = impegnato +ACEM = maturato +CONS = fatturato +CNTBZ = checazzoneso + +//Calcolatore per tipi (AN,PN),FM +calcolatore (const int tipo, const int classe, const int dare) +{ + const int segno = classe * dare; //essendo classe e dare = + o - 1, il segno lo si ottiene direttamente + if (classe == 1 && dare == -1) //unico caso in cui non rispetta il prodotto dei segni + { + I_ACEM = (I_ACEM - segno * NEW_ACEMVAL) * tipo; //tipo = 1 se AN,PN; = 0 se FM + I_STIMA = I_STIMA - segno * NEW_STIMAVAL; + } + else + { + I_ACEM = (I_ACEM + segno * NEW_ACEMVAL) * tipo; + I_STIMA = I_STIMA + segno * NEW_STIMAVAL; + } + + //questa è comunque sempre corretta + I_CNTBZ = I_CNTBZ + segno * NEW_ICNTBZVAL; +} + + +//Calcolatore per tipi (OA,OV) -> impegnato, (BA,BV) -> impegnato, (FA,FN) -> impegnato, +calcolatore (const int tipo) +{ + switch (tipo): + case OA: + case OV: + I_COMM = I_COMM + NEW_COMMVAL; + break; + + case BA: + case BV: + I_ACEM = I_ACEM + NEW_ACEMVAL; + break; + + case FA: + case FN: + I_CONS = I_CONS + NEW_CONSVAL; + break; +} + + +*/ \ No newline at end of file diff --git a/ca/ca3700.h b/ca/ca3700.h index 444009268..1e2dd62b3 100755 --- a/ca/ca3700.h +++ b/ca/ca3700.h @@ -23,7 +23,10 @@ //sheet di pagina 2 #define F_RIGHE 260 +//sheet di pagina 3 +#define F_RIGHE_NUM 270 +//elementi dello sheet con CdC/Cms/Fas (pag.2) #define S_CDC1 101 #define S_CDC2 102 #define S_CDC3 103 @@ -37,5 +40,9 @@ #define S_CDC11 111 #define S_CDC12 112 +//elementi dello sheet dei documenti (pag.3) +#define SN_CODNUM 101 +#define SN_DESCR 102 + #endif // __CA3700_H diff --git a/ca/ca3700.uml b/ca/ca3700.uml index 2b09ce41b..69d23c4ce 100755 --- a/ca/ca3700.uml +++ b/ca/ca3700.uml @@ -21,7 +21,7 @@ END ENDPAGE -PAGE "Parametri stampa" -1 -1 78 20 +PAGE "Conti / Date" -1 -1 78 20 NUMBER F_CODDITTA 5 BEGIN @@ -73,7 +73,7 @@ BEGIN PROMPT 1 10 "@bA:" END -GROUPBOX DLG_NULL 76 7 +GROUPBOX DLG_NULL 76 4 BEGIN PROMPT 1 16 "@bOpzioni stampa" END @@ -100,14 +100,14 @@ END STRING F_REPORT 256 64 BEGIN - PROMPT 2 21 "Report " + PROMPT 2 18 "Report " FLAGS "B" CHECKTYPE REQUIRED END ENDPAGE -PAGE "Selezioni" -1 -1 78 20 +PAGE "CdC / Cms / Fasi" -1 -1 78 20 SPREADSHEET F_RIGHE -1 -2 BEGIN @@ -128,9 +128,21 @@ END ENDPAGE +PAGE "Numerazioni doc" -1 -1 78 20 + +SPREADSHEET F_RIGHE_NUM -1 -2 +BEGIN + PROMPT 1 2 "" + ITEM "Numerazione" +// ITEM "Tipo" + ITEM "Descrizione@50" +END + +ENDPAGE + ENDMASK -PAGE "Riga" -1 -1 78 19 +PAGE "Riga Analitica" -1 -1 78 19 STRING S_CDC1 20 BEGIN @@ -245,4 +257,50 @@ END ENDPAGE +ENDMASK + + +PAGE "Riga Numerazione" -1 -1 78 5 + +STRING SN_CODNUM 4 +BEGIN + PROMPT 1 1 "Codice numerazione " + USE %NUM + CHECKTYPE REQUIRED + INPUT CODTAB SN_CODNUM + DISPLAY "Codice" CODTAB + DISPLAY "Descrizione@50" S0 + OUTPUT SN_CODNUM CODTAB + OUTPUT SN_DESCR S0 + KEY 1 + FLAGS "UZ" +END + +STRING SN_DESCR 50 +BEGIN + PROMPT 1 2 "Descrizione " + USE %NUM KEY 2 + INPUT S0 SN_DESCR + DISPLAY "Descrizione@50" S0 + DISPLAY "Codice" CODTAB + COPY OUTPUT SN_CODNUM +END + +BUTTON DLG_OK 10 2 +BEGIN + PROMPT -13 -1 "" +END + +BUTTON DLG_DELREC 10 2 +BEGIN + PROMPT -23 -1 "" +END + +BUTTON DLG_CANCEL 10 2 +BEGIN + PROMPT -33 -1 "" +END + +ENDPAGE + ENDMASK \ No newline at end of file