2010-09-01 15:47:38 +00:00
# include <applicat.h>
# include <automask.h>
# include <progind.h>
# include <recarray.h>
# include <recset.h>
# include <reputils.h>
# include <doc.h>
# include <rdoc.h>
# include "../cg/cglib01.h"
# include "../ve/velib.h"
# include "halib.h"
# include "ha0.h"
# include "ha0500a.h"
///////////////////////////////////////////////////////////
// TAutomask
///////////////////////////////////////////////////////////
class THardy_elab_docs_mask : public TAutomask
{
protected :
virtual bool on_field_event ( TOperable_field & o , TField_event e , long jolly ) ;
public :
THardy_elab_docs_mask ( ) ;
~ THardy_elab_docs_mask ( ) ;
} ;
THardy_elab_docs_mask : : THardy_elab_docs_mask ( ) : TAutomask ( " ha0500a " )
{
}
THardy_elab_docs_mask : : ~ THardy_elab_docs_mask ( )
{
}
bool THardy_elab_docs_mask : : on_field_event ( TOperable_field & o , TField_event e , long jolly )
{
switch ( o . dlg ( ) )
{
case F_ADATA :
if ( e = = fe_close | | e = = fe_modify )
{
//se la data iniziale <20> piena -> l'anno deve essere lo stesso nelle 2 date;
//se invece <20> vuota -> la data iniziale viene presa come la data iniziale dell'esercizio della data finale...
//..ma questo qui non serve e viene rinviato alla query principale del recordset
const TDate adata = get_date ( F_ADATA ) ;
TEsercizi_contabili esc ;
const int adata_esc = esc . date2esc ( adata ) ;
TDate dadata = o . get ( ) ;
if ( dadata . ok ( ) )
{
const int dadata_esc = esc . date2esc ( dadata ) ;
if ( adata_esc ! = dadata_esc )
return error_box ( " Le date devono appartenere allo stesso esercizio! " ) ;
}
}
break ;
/*case F_TIPOCONTR:
if ( e = = fe_modify )
{
//in base alla tipologia di contratti da elaborare decide numerazione e tipo delle NAC da generare
TConfig config ( CONFIG_DITTA , " ha " ) ;
TString4 codnum , tipodoc ;
switch ( o . get ( ) [ 0 ] )
{
case ' A ' :
codnum = config . get ( " NaAntNum " ) ;
tipodoc = config . get ( " NaAntTip " ) ;
break ;
case ' R ' :
codnum = config . get ( " NaRifaNum " ) ;
tipodoc = config . get ( " NaRifaTip " ) ;
break ;
default :
codnum = config . get ( " NaPostNum " ) ;
tipodoc = config . get ( " NaPostTip " ) ;
break ;
}
set ( F_CODNUM_NAC , codnum ) ;
set ( F_CODTIPO_NAC , tipodoc ) ;
}
break ; */
//in caso di elaborazione definitiva <20> obbligatorio..
//..eliminare tutte le NAC provvisorie generate in precedenza
case F_DEFINITIVO :
if ( e = = fe_modify )
{
if ( o . get ( ) = = " X " )
{
set ( F_KILLPROVV , " X " ) ;
disable ( F_KILLPROVV ) ;
}
else
{
enable ( F_KILLPROVV ) ;
set ( F_KILLPROVV , " " ) ;
}
}
break ;
default :
break ;
}
return true ;
}
///////////////////////////////////////
// TSkeleton_application
///////////////////////////////////////
class THardy_elab_docs : public TSkeleton_application
{
protected :
//metodi alto livello
void elabora ( const TMask & mask ) ;
int kill_provv_nac ( const TMask & mask ) ;
long genera_recordset ( const TMask & mask , TISAM_recordset & recset ) ;
void elabora_documenti ( const TMask & mask , TISAM_recordset & recset , TLog_report & log ) ;
//metodi medio livello
2010-09-27 14:30:54 +00:00
bool aggiorna_contratti ( const TRiga_documento & rdoc , TContratto_premi & contratto ) ;
2010-09-13 13:39:46 +00:00
bool elabora_contratti ( TDocumento & curr_doc , TArray & contratti_cliente ) ;
2010-09-01 15:47:38 +00:00
bool genera_nac ( const TMask & mask , TArray & contratti_cliente , TArray & documenti_cliente , TLog_report & log ) ;
//metodi basso livello
int find_contratti_cliente ( const long codcf , const TMask & mask , TArray & contratti_cliente ) ;
void check_date ( const TDate & datafine , TDate & dataini ) ;
int find_numerazioni ( const TString & tipo_to_elab , TString_array & num_doc ) ;
public :
virtual void main_loop ( ) ;
virtual bool create ( ) ;
} ;
//metodo per ricavare la data iniziale di elaborazione qualora l'utonto non la metta e l'esercizio da usare
void THardy_elab_docs : : check_date ( const TDate & datafine , TDate & dataini )
{
TEsercizi_contabili esc ;
TDate datafine_tmp = datafine ;
const int esercizio = esc . date2esc ( datafine ) ;
esc . code2range ( esercizio , dataini , datafine_tmp ) ;
}
int THardy_elab_docs : : find_numerazioni ( const TString & tipo_to_elab , TString_array & num_doc )
{
TISAM_recordset num_recset ( " USE %NUM " ) ;
for ( bool ok = num_recset . move_first ( ) ; ok ; ok = num_recset . move_next ( ) ) //giro sui vari tipi numerazione
{
const TString4 codtab = num_recset . get ( " CODTAB " ) . as_string ( ) ;
const TCodice_numerazione numerazione ( codtab ) ;
for ( int t = numerazione . ntipi_doc ( ) - 1 ; t > = 0 ; t - - )
{
const TString & tipo_doc = numerazione . tipo_doc ( t ) ;
if ( tipo_doc = = tipo_to_elab )
{
if ( num_doc . find ( codtab ) < 0 ) // Evito aggiunta di doppioni
num_doc . add ( codtab ) ;
break ;
}
} //for (int t = codnum..
} //for (bool ok = num_recset...
return num_doc . items ( ) ;
}
//metodo per accoppare tutte le NAC provvisorie generate in precedenza
int THardy_elab_docs : : kill_provv_nac ( const TMask & mask )
{
int nac_killed = 0 ;
const TDate & adata = mask . get_date ( F_ADATA ) ;
int anno = adata . year ( ) ;
TConfig config ( CONFIG_DITTA , " ha " ) ;
TToken_string numerazioni ;
numerazioni . add ( config . get ( " NaAntNum " ) ) ;
numerazioni . add ( config . get ( " NaRifaNum " ) ) ;
numerazioni . add ( config . get ( " NaPostNum " ) ) ;
FOR_EACH_TOKEN ( numerazioni , codnum )
{
TRelation rel_doc ( LF_DOC ) ;
TRectype & rec = rel_doc . curr ( ) ;
rec . put ( DOC_PROVV , " P " ) ;
rec . put ( DOC_ANNO , anno ) ;
rec . put ( DOC_CODNUM , codnum ) ;
TCursor cur_doc ( & rel_doc , " " , 1 , & rec , & rec ) ;
const long items = cur_doc . items ( ) ;
cur_doc . freeze ( ) ;
TProgind progind ( items , " Eliminazione NAC provvisorie in corso... " , false , true ) ;
for ( cur_doc = 0 ; cur_doc . pos ( ) < items ; + + cur_doc )
{
progind . addstatus ( 1 ) ;
TDocumento doc ( rec ) ;
int err = doc . remove ( ) ;
if ( err = = NOERR )
nac_killed + + ;
}
}
return nac_killed ;
}
//metodo che filtra tutti i documenti in base ai parametri della maschera
long THardy_elab_docs : : genera_recordset ( const TMask & mask , TISAM_recordset & recset )
{
//parametri di elaborazione
//per prima cosa controlla se il cliente <20> stato specificato; questo influisce sulla scelta della chiave di ricerca sul file
int key = 3 ;
const long codcf = mask . get_long ( F_CODCF ) ;
if ( codcf > 0 )
key = 2 ;
//e costruiamola 'sta query!
//usa i documenti con chiave variabile (vedi sopra)
TString query ;
query < < " USE DOC KEY " < < key ;
//lo stato dipende da quanto sta scritto sulla elaborazione differita (stato iniziale dei docs da considerare)
//viene messo CODNUM nella SELECT perch<63> , essendoci un range di date nelle chiavi, la numerazione verrebbe ignorata! (provato!)
query < < " \n SELECT (STATO=#STATOINI) " ;
//in base al tipo documento che si deve elaborare (settato in configurazione), ci possono essere pi<70> numerazioni da considerare!
TConfig config ( CONFIG_DITTA , " ha " ) ;
const TString & tipo_to_elab = config . get ( " TipoFatt " ) ;
//e adesso cerca le numerazioni che contengono il tipo preso dalla configurazione
TString_array num_doc ;
const int numerazioni_valide = find_numerazioni ( tipo_to_elab , num_doc ) ;
if ( numerazioni_valide > 0 )
{
query < < " &&( " ;
for ( int i = 0 ; i < numerazioni_valide ; i + + )
{
if ( i > 0 )
query < < " || " ;
query < < " (CODNUM=' " < < num_doc [ i ] < < " ') " ;
}
query < < " ) " ;
}
//se c'<27> l'agente specificato...
const TString & agente = mask . get ( F_CODAGE ) ;
const bool has_007 = agente . full ( ) ;
if ( has_007 )
query < < " &&(CODAG=#CODAG) " ;
//ordinamento agente-codcf-numdoc
query < < " \n BY " ;
if ( has_007 )
query < < DOC_CODAG < < " " ;
query < < DOC_CODCF < < " " < < DOC_NDOC ;
//from-to dipendente da chiave
switch ( key )
{
case 2 : //chiave per tipocf-codcf-provv-anno-datadoc-codnum
{
query < < " \n FROM TIPOCF=C CODCF=#CODCF PROVV=D ANNO=#ANNO DATADOC=#DADATA " ;
query < < " \n TO TIPOCF=C CODCF=#CODCF PROVV=D ANNO=#ANNO DATADOC=#ADATA " ;
}
break ;
case 3 : //chiave per datadoc-provv-anno-codnum
{
query < < " \n FROM DATADOC=#DADATA PROVV=D ANNO=#ANNO " ;
query < < " \n TO DATADOC=#ADATA PROVV=D ANNO=#ANNO " ;
}
break ;
default :
break ;
}
//setta la nuova query al recordset (inizialmente nato dequeryzzato)
recset . set ( query ) ;
//settaggio delle variabili
const TDate adata = mask . get_date ( F_ADATA ) ;
TDate dadata = mask . get_date ( F_DADATA ) ;
//se la data iniziale <20> vuota deve coincidere con l'inizio dell'esercizio della data finale (obbligatoria!)
int esc = adata . year ( ) ;
if ( ! dadata . ok ( ) )
check_date ( adata , dadata ) ;
//lo stato dei documenti da considerare va a raccatarlo nel config
const TString & stato_ini = config . get ( " StatoIniFatt " ) ;
recset . set_var ( " #STATOINI " , stato_ini ) ;
if ( agente . full ( ) )
recset . set_var ( " #CODAG " , agente ) ;
if ( codcf > 0 )
recset . set_var ( " #CODCF " , codcf ) ;
recset . set_var ( " #ANNO " , long ( esc ) ) ;
recset . set_var ( " #DADATA " , dadata ) ;
recset . set_var ( " #ADATA " , adata ) ;
return recset . items ( ) ;
}
//metodo che riempie un array con tutti i contratti del cliente passatogli (in base alla tipologia di contratti da elaborare)
int THardy_elab_docs : : find_contratti_cliente ( const long codcf , const TMask & mask , TArray & contratti_cliente )
{
contratti_cliente . destroy ( ) ;
//deve cercare tutti i contratti del cliente e metterli nell'array
TString query ;
query < < " USE DOC KEY 4 " ;
2010-09-27 14:30:54 +00:00
query < < " \n SELECT ((TIPODOC=#A_TIPODOC)||(TIPODOC=#R_TIPODOC)||(TIPODOC=#P_TIPODOC)) " ;
2010-09-01 15:47:38 +00:00
query < < " \n FROM TIPOCF=C CODCF=#CODCF " ;
query < < " \n TO TIPOCF=C CODCF=#CODCF " ;
TISAM_recordset recset ( query ) ;
//settaggio delle variabili
//il codice numerazione lo trova nella configurazione Hardy, e lo deve scegliere in base alla tipologia di contratti che sta esaminando!
TConfig config ( CONFIG_DITTA , " ha " ) ;
2010-09-27 14:30:54 +00:00
const TString & tip_ant = config . get ( " CoAntTip " ) ;
const TString & tip_rifa = config . get ( " CoRifaTip " ) ;
const TString & tip_post = config . get ( " CoPostTip " ) ;
2010-09-01 15:47:38 +00:00
2010-09-27 14:30:54 +00:00
recset . set_var ( " #A_TIPODOC " , tip_ant ) ;
recset . set_var ( " #R_TIPODOC " , tip_rifa ) ;
recset . set_var ( " #P_TIPODOC " , tip_post ) ;
2010-09-01 15:47:38 +00:00
recset . set_var ( " #CODCF " , codcf ) ;
const long n_contratti = recset . items ( ) ; //questo serve solo al sagace programmatore
//aggiunge i contratti all'array: solo quelli in auge nel periodo di calcolo selezionato sulla maschera!
for ( bool ok = recset . move_first ( ) ; ok ; ok = recset . move_next ( ) )
{
//contratti anticipo 'A': datainizio esiste sempre, datafine non esiste (va ad esaurimento)
//contratti posticipo 'P': datainizio esiste sempre, datafine pu<70> non esistere
//contratti rifatturazione 'R': come contratti anticipo
//controlla validit<69> del contratto con le date scelte per l'elaborazione dei documenti
const TDate data_ini_contratto = recset . get ( DOC_DATACOMP ) . as_date ( ) ;
TDate data_ini_elab = mask . get_date ( F_DADATA ) ;
const TDate data_fine_elab = mask . get_date ( F_ADATA ) ;
if ( ! data_ini_elab . ok ( ) )
check_date ( data_fine_elab , data_ini_elab ) ;
//quindi la datainizio vale per tutti allo stesso modo (<28> obbligatoria nei contratti)
//se l'elaborazione finisce prima che cominci il contratto -> il contratto non serve a nulla
if ( data_ini_contratto > data_fine_elab )
continue ;
//la data fine vale invece solo per i contratti 'P' e potrebbe non esserci (contratti senza scadenza)
TDate data_fine_contratto ;
2010-09-27 14:30:54 +00:00
//se la data fine contratto non <20> valida (ma <20> presente!) non dobbiamo fare nulla, perch<63> il contratto non va elaborato
data_fine_contratto = recset . get ( DOC_DATAFCOMP ) . as_date ( ) ;
if ( data_fine_contratto . ok ( ) )
{
if ( data_fine_contratto < data_ini_elab )
continue ;
}
//ci tocca istanziarci un contratto_premi
TContratto_premi * curr_contratto = new TContratto_premi ( recset . cursor ( ) - > curr ( ) ) ;
//azzeratore del campo con il totale reso per elaborazione, nel caso di contratti Anticipo/Rifatturazione, riga spese
const char tipo_contr = curr_contratto - > tipo_contratto ( ) ;
if ( tipo_contr = = ' A ' | | tipo_contr = = ' R ' )
2010-09-01 15:47:38 +00:00
{
2010-09-27 14:30:54 +00:00
FOR_EACH_PHYSICAL_RDOC ( * curr_contratto , r , rdoc )
2010-09-01 15:47:38 +00:00
{
2010-09-27 14:30:54 +00:00
if ( rdoc - > get ( RDOC_TIPORIGA ) = = HARDY_TIPORIGA_SOMMA )
{
rdoc - > zero ( RCA_2_RESO_CORRENTE ) ;
break ;
}
2010-09-01 15:47:38 +00:00
}
}
contratti_cliente . add ( curr_contratto ) ;
}
return contratti_cliente . items ( ) ;
}
2010-09-27 14:30:54 +00:00
bool THardy_elab_docs : : aggiorna_contratti ( const TRiga_documento & rdoc , TContratto_premi & contratto )
2010-09-01 15:47:38 +00:00
{
bool elaborato = false ;
2010-09-27 14:30:54 +00:00
const char tipo_contratto = contratto . tipo_contratto ( ) ;
2010-09-13 13:39:46 +00:00
//parametri della riga fattura
TString80 rdoc_codart = rdoc . get ( RDOC_CODART ) ;
rdoc_codart . trim ( ) ;
const real rdoc_qta = rdoc . get_real ( RDOC_QTA ) ;
const TString4 rdoc_umqta = rdoc . get ( RDOC_UMQTA ) ;
2010-09-01 15:47:38 +00:00
FOR_EACH_PHYSICAL_RDOC ( contratto , rm , rigamerce )
{
const TString & rigamerce_codart = rigamerce - > get ( RDOC_CODART ) ;
//se trova il codart in una delle righe di contratto...
if ( rdoc_codart = = rigamerce_codart )
{
const real rigamerce_premio = rigamerce - > get_real ( RC_1_PREMIO ) ;
2010-09-13 13:39:46 +00:00
//se il premio non <20> nullo procede all'aggiornamento del restituito (solo contratti A/R e righe spese) e del bonus (tutti i contratti e righe merce)
2010-09-01 15:47:38 +00:00
if ( rigamerce_premio ! = ZERO )
{
2010-09-13 13:39:46 +00:00
//normalizzazione della qta
const TString & umqta_tot = rigamerce - > get ( RDOC_UMQTA ) ; //prende la UM dal contratto che far<61> da riferimento!
TArticolo articolo ( rdoc_codart ) ;
const real normalized_rdoc_qta = articolo . convert_to_um ( rdoc_qta , umqta_tot , rdoc_umqta , true ) ;
//aggiornamento delle righe di tipo spesa (verigh02) per aggiornare le somme restituite nel caso di contratti di anticipo/rifatturazione
if ( tipo_contratto = = ' A ' | | tipo_contratto = = ' R ' )
2010-09-01 15:47:38 +00:00
{
2010-09-13 13:39:46 +00:00
FOR_EACH_PHYSICAL_RDOC ( contratto , ra , rigacontratto )
2010-09-01 15:47:38 +00:00
{
2010-09-13 13:39:46 +00:00
//cerca una riga anticipo da evadere sul contratto per aggiornare la somma restituita sull'anticipo
if ( rigacontratto - > is_spese ( ) )
{
2010-09-27 14:30:54 +00:00
//si informa su quale fosse la somma anticipata
const real somma_anticipata = rigacontratto - > get_real ( RCA_2_ANTICIPATO ) ;
2010-09-13 13:39:46 +00:00
//aggiorna la somma restituita dovuta al contratto (parte da zero per ogni elaborazione di NAC)
2010-09-27 14:30:54 +00:00
real somma_restituita = rigacontratto - > get_real ( RCA_2_RESO_CORRENTE ) ;
//controlla che il contratto non sia per caso gi<67> stato pareggiato! quindi il reso deve essere < dell'anticipato per procedere
2010-09-13 13:39:46 +00:00
//la somma restituita deve essere incrementata per la qta di merce (caff<66> ) che c'<27> sulla riga della fattura in esame...
//..moltiplicata per il premio che c'<27> nella riga di tipo merce del contratto in esame
somma_restituita + = normalized_rdoc_qta * rigamerce_premio ;
2010-09-27 14:30:54 +00:00
rigacontratto - > put ( RCA_2_RESO_CORRENTE , somma_restituita ) ;
2010-09-13 13:39:46 +00:00
elaborato = true ;
break ;
2010-09-27 14:30:54 +00:00
2010-09-13 13:39:46 +00:00
}
} //FOR_EACH_PHYSICAL.. fine casino sulla riga di tipo spese
} //if(tipo_contratto == "A"...
//questo va bene invece per ogni riga merce (verigh01), sia per contratti di tipo A/R che di tipo P
2010-09-01 15:47:38 +00:00
if ( rigamerce - > is_merce ( ) )
{
real somma_bonus = rigamerce - > get_real ( RC_1_BONUS ) ;
2010-09-13 13:39:46 +00:00
somma_bonus + = normalized_rdoc_qta * rigamerce_premio ;
2010-09-01 15:47:38 +00:00
rigamerce - > put ( RC_1_BONUS , somma_bonus ) ;
2010-09-13 13:39:46 +00:00
rigamerce - > add ( RDOC_QTA , normalized_rdoc_qta ) ; //riscrive sul campo di appoggio del contratto
2010-09-01 15:47:38 +00:00
elaborato = true ;
}
2010-09-13 13:39:46 +00:00
} //if(rigamerce_premio != ZERO...
2010-09-01 15:47:38 +00:00
} //if(rdoc_codart...
} //FOR_EACH_PHYSICAL..
return elaborato ;
}
//aggiorna, in base al documento in esame curr_doc, le somme restituite nelle righe di tipo verigh02 nei contratti validi..
//..del cliente
2010-09-13 13:39:46 +00:00
bool THardy_elab_docs : : elabora_contratti ( TDocumento & curr_doc , TArray & contratti_cliente )
2010-09-01 15:47:38 +00:00
{
bool elaborato = false ;
FOR_EACH_PHYSICAL_RDOC ( curr_doc , r , rdoc ) if ( rdoc - > is_merce ( ) ) //giro su tutte le righe merce delle fatture
{
TString80 rdoc_codart = rdoc - > get ( RDOC_CODART ) ; //non si riesce ad usare un TString& perch<63> lo perde dopo un p<>
rdoc_codart . trim ( ) ;
const real rdoc_qta = rdoc - > quantita ( ) ;
//controlla se il codart della riga esiste in uno dei contratti validi
for ( int i = 0 ; i < contratti_cliente . items ( ) ; i + + )
{
2010-09-27 14:30:54 +00:00
TContratto_premi & contratto = ( TContratto_premi & ) contratti_cliente [ i ] ;
2010-09-13 13:39:46 +00:00
elaborato | = aggiorna_contratti ( * rdoc , contratto ) ;
2010-09-01 15:47:38 +00:00
} //for(int i..
} //FOR_EACH...
return elaborato ;
}
bool THardy_elab_docs : : genera_nac ( const TMask & mask , TArray & contratti_cliente , TArray & documenti_cliente , TLog_report & log )
{
//si informa se l'elaborazione <20> definitiva o meno
const bool definitivo = mask . get_bool ( F_DEFINITIVO ) ;
//giro su tutti i contratti del cliente che stanno nell'array (ogni contratto genera una NAC)
FOR_EACH_ARRAY_ITEM ( contratti_cliente , r , riga )
{
2010-09-27 14:30:54 +00:00
TContratto_premi & contratto = * ( TContratto_premi * ) riga ;
2010-09-01 15:47:38 +00:00
const long ndoc = contratto . numero ( ) ; //il numdoc del contratto serve nelle segnalazioni
const long codcf = contratto . codcf ( ) ; //il codice cliente ci serve nella generazione della NAC..
2010-09-27 14:30:54 +00:00
const char tipo_contratto = contratto . tipo_contratto ( ) ; //..e pure il tipo di contratto in esame!
2010-09-01 15:47:38 +00:00
//segnaliamo l'elaborazione del contratto sul log
2010-09-27 14:30:54 +00:00
TString log_msg ;
log_msg . format ( " Contratto:%6ld Cliente:%6ld " , ndoc , codcf ) ;
//log_msg << "Contratto: " << ndoc << " Cliente: " << codcf;
2010-09-01 15:47:38 +00:00
// generazione del documento NAC dal contratto
// -------------------------------------------
// TESTATA
//alcuni parametri delle righe vanno presi dalla configurazione
TConfig config ( CONFIG_DITTA , " ha " ) ;
TString4 nac_codnum , nac_tipo ;
TString8 cod_riga ;
switch ( tipo_contratto )
{
case ' A ' :
nac_codnum = config . get ( " NaAntNum " ) ;
nac_tipo = config . get ( " NaAntTip " ) ;
cod_riga = config . get ( " NaAntSpe " ) ;
break ;
case ' R ' :
nac_codnum = config . get ( " NaRifaNum " ) ;
nac_tipo = config . get ( " NaRifaTip " ) ;
cod_riga = config . get ( " NaRifaSpe " ) ;
break ;
default :
nac_codnum = config . get ( " NaPostNum " ) ;
nac_tipo = config . get ( " NaPostTip " ) ;
cod_riga = config . get ( " NaPostSpe " ) ;
break ;
}
const int anno = mask . get_date ( F_ADATA ) . year ( ) ;
//solo in caso di elaborazione definitiva si scrivono NAC di tipo D; senn<6E> di tipo P, che sono uccidibili..
//..all'inizio di ogni nuova elaborazione
char provv = ' P ' ;
if ( definitivo )
provv = ' D ' ;
TDocumento nac ( provv , anno , nac_codnum , 0 ) ; //num_doc = 0 perch<63> viene aggiornato in fase di registrazione
nac . set_tipo ( nac_tipo ) ;
nac . put ( DOC_STATO , 1 ) ;
nac . put ( DOC_DATADOC , mask . get ( F_DATAELAB ) ) ;
nac . put ( DOC_TIPOCF , ' C ' ) ;
nac . put ( DOC_CODCF , codcf ) ;
// RIGHE
//ogni riga di tipo merce (verigh01) del contratto origina una riga della NAC
//noto il codice di riga spesa (che far<61> le veci del codart), troviamo il tipo riga dalla tabella SPP e tutte le features che servono
const TRectype & rec_spp = cache ( ) . get ( " SPP " , cod_riga ) ;
const TString4 tipo_riga = rec_spp . get ( " S8 " ) ;
const TString80 descr_riga_spp = rec_spp . get ( " S0 " ) ;
const TString4 codiva = rec_spp . get ( " S3 " ) ;
//giro sulle righe del contratto, che originano le righe NAC
for ( int i = 1 ; i < = contratto . rows ( ) ; i + + )
{
const TRiga_documento & riga_contratto = contratto [ i ] ; //le righe di un documento partono da 1! (standard del mercoled<65> )
const TString & tiporiga = riga_contratto . get ( RDOC_TIPORIGA ) ;
2010-09-27 14:30:54 +00:00
TString80 riga_contratto_codart = riga_contratto . get ( RDOC_CODART ) ;
2010-09-01 15:47:38 +00:00
//solo le righe di tipo merce (verigh01) dei contratti devono comparire nelle NAC
2010-09-27 14:30:54 +00:00
if ( tiporiga = = HARDY_TIPORIGA_MERCE )
2010-09-01 15:47:38 +00:00
{
const real riga_contratto_qta = riga_contratto . get_real ( RDOC_QTA ) ;
const TString4 riga_contratto_um = riga_contratto . get ( RDOC_UMQTA ) ;
const real riga_contratto_premio = riga_contratto . get_real ( RC_1_PREMIO ) ;
2010-09-27 14:30:54 +00:00
// riga merce NAC
2010-09-01 15:47:38 +00:00
TRiga_documento & nac_row = nac . new_row ( tipo_riga ) ;
nac_row . put ( RDOC_CODART , cod_riga ) ;
//panegirico della descrizione
nac_row . put ( RDOC_DESCR , descr_riga_spp ) ;
2010-09-27 14:30:54 +00:00
TString msg ;
2010-09-01 15:47:38 +00:00
const TDate adata = mask . get_date ( F_ADATA ) ;
TDate dadata = mask . get_date ( F_DADATA ) ;
if ( ! dadata . ok ( ) )
check_date ( adata , dadata ) ;
msg < < " " < < dadata < < " -- " < < adata < < " --(Art. " < < riga_contratto_codart < < " ) " ;
nac_row . put ( RDOC_DESCEST , msg ) ;
nac_row . put ( RDOC_DESCLUNGA , " X " ) ;
//importi, qta, umqta
nac_row . put ( RDOC_UMQTA , riga_contratto_um ) ;
nac_row . put ( RDOC_QTA , riga_contratto_qta ) ;
nac_row . put ( RDOC_PREZZO , riga_contratto_premio ) ;
//iva
nac_row . put ( RDOC_CODIVA , codiva ) ;
}
2010-09-27 14:30:54 +00:00
//trattazione speciale delle righe spese (verigh02) (solo 'A'nticipi e 'R'ifatturazioni)
if ( tiporiga = = HARDY_TIPORIGA_SOMMA & & ( tipo_contratto = = ' A ' | | tipo_contratto = = ' R ' ) )
{
const real somma_anticipata = riga_contratto . get_real ( RCA_2_ANTICIPATO ) ;
real somma_resa_storica = riga_contratto . get_real ( RCA_2_RESO_STORICO ) ;
real somma_resa_corrente = riga_contratto . get_real ( RCA_2_RESO_CORRENTE ) ;
const real esubero = somma_resa_storica + somma_resa_corrente - somma_anticipata ;
if ( esubero > ZERO )
{
somma_resa_corrente - = esubero ;
//se c'<27> un esubero nel rimborso dell'anticipo esister<65> solo una riga nella NAC, con una cifra pari alla somma..
//..che mancava a pareggiare l'anticipo (anche se l'esubero eccedesse tale differenza, sulla NAC ci va la somma a..
//..pareggio! cos<6F> freghiamo qualcosa al cliente)
nac . destroy_rows ( ) ;
// riga spesa NAC
TRiga_documento & nac_row = nac . new_row ( tipo_riga ) ;
nac_row . put ( RDOC_CODART , cod_riga ) ;
//panegirico della descrizione
nac_row . put ( RDOC_DESCR , descr_riga_spp ) ;
TString msg ;
const TDate adata = mask . get_date ( F_ADATA ) ;
TDate dadata = mask . get_date ( F_DADATA ) ;
if ( ! dadata . ok ( ) )
check_date ( adata , dadata ) ;
msg < < " " < < dadata < < " -- " < < adata ;
nac_row . put ( RDOC_DESCEST , msg ) ;
nac_row . put ( RDOC_DESCLUNGA , " X " ) ;
//importi, qta
nac_row . put ( RDOC_QTA , 1 ) ;
nac_row . put ( RDOC_PREZZO , somma_resa_corrente ) ;
//iva
nac_row . put ( RDOC_CODIVA , codiva ) ;
}
}
2010-09-01 15:47:38 +00:00
}
// salvataggi vari
// ---------------
2010-09-27 14:30:54 +00:00
// NAC
// viene scritta comunque, con provv='D' se elaborazione definitiva
2010-09-01 15:47:38 +00:00
int err = nac . write ( ) ;
2010-09-27 14:30:54 +00:00
TString wrk_msg ;
2010-09-01 15:47:38 +00:00
if ( err = = NOERR )
2010-09-27 14:30:54 +00:00
{
wrk_msg . format ( " -- Generata NAC: %-4s%-4s%c %7ld " , ( const char * ) nac_codnum , ( const char * ) nac_tipo , provv , nac . get_long ( DOC_NDOC ) ) ;
log_msg < < wrk_msg ;
}
2010-09-01 15:47:38 +00:00
else
2010-09-27 14:30:54 +00:00
log_msg < < " -- Impossibile generare NAC !! " ;
// CONTRATTO
//se il contratto <20> di tipo A/R aggiorna la riga spese speciale (verigh02)
if ( ( tipo_contratto = = ' A ' | | tipo_contratto = = ' R ' ) & & err = = NOERR )
{
FOR_EACH_PHYSICAL_RDOC ( contratto , r , rdoc )
{
if ( rdoc - > get ( RDOC_TIPORIGA ) = = HARDY_TIPORIGA_SOMMA )
{
const real anticipato = rdoc - > get_real ( RCA_2_ANTICIPATO ) ;
real reso_storico = rdoc - > get_real ( RCA_2_RESO_STORICO ) ;
reso_storico + = rdoc - > get_real ( RCA_2_RESO_CORRENTE ) ;
rdoc - > put ( RCA_2_RESO_STORICO , reso_storico ) ;
//se il contratto <20> andato a pareggio avverte dilegentemente l'operatore
if ( reso_storico > = anticipato )
log_msg < < " -- Contratto pareggiato! " ;
} //if (rdoc->get(RDOC_TIPORIGA)...
} //FOR_EACH_PHYSICAL_RDOC(contratto...
} //if (tipo_contratto == 'A'..
2010-09-01 15:47:38 +00:00
// se non ci sono errori -> in caso di elaborazione definitiva procede alla registrazione..
//.. del contratto (ricordiamo che in memoria il contratto ha gi<67> le righe aggiornate
if ( definitivo & & err = = NOERR )
{
//alla fine della fiera aggiorna il contratto
err = contratto . rewrite ( ) ;
2010-09-27 14:30:54 +00:00
2010-09-01 15:47:38 +00:00
if ( err = = NOERR )
2010-09-27 14:30:54 +00:00
log_msg < < " -- Contratto aggiornato " ;
2010-09-01 15:47:38 +00:00
else
2010-09-27 14:30:54 +00:00
log_msg < < " -- Impossibile aggiornare contratto " ;
2010-09-01 15:47:38 +00:00
}
2010-09-27 14:30:54 +00:00
log . log ( 0 , log_msg ) ;
2010-09-01 15:47:38 +00:00
log . log ( 0 , " " ) ;
} //FOR_EACH_ARRAY_ITEM(... giro sui contratti cliente
//il metodo ritorner<65> il successo o meno della registrazione
return true ;
}
2010-09-27 14:30:54 +00:00
void THardy_elab_docs : : elabora_documenti ( const TMask & mask , TISAM_recordset & fatture , TLog_report & log )
2010-09-01 15:47:38 +00:00
{
2010-09-27 14:30:54 +00:00
TProgind pi ( fatture . items ( ) , TR ( " Elaborazione documenti in corso... " ) , true , true ) ;
2010-09-01 15:47:38 +00:00
//inizializza variabili da usare nella scansione del recordset
long old_codcf = 0L ;
//array con l'insieme dei contratti e dei documenti elaborati per un singolo cliente!
TArray contratti_cliente , documenti_cliente ;
2010-09-13 13:39:46 +00:00
//giro sulle fatture (<28> il giro di pi<70> alto livello che viene esteso all'interno delle elabora_contratti)
2010-09-27 14:30:54 +00:00
for ( bool ok = fatture . move_first ( ) ; ok ; ok = fatture . move_next ( ) )
2010-09-01 15:47:38 +00:00
{
if ( ! pi . addstatus ( 1 ) )
break ;
2010-09-27 14:30:54 +00:00
const long codcf = fatture . get ( DOC_CODCF ) . as_int ( ) ;
2010-09-01 15:47:38 +00:00
//al cambio cliente deve controllare i contratti di quel cliente nel periodo di elaborazione!!
if ( codcf ! = old_codcf )
{
2010-09-27 14:30:54 +00:00
//generazione NAC del cliente precedente (una per contratto cliente)
if ( old_codcf > 0 )
genera_nac ( mask , contratti_cliente , documenti_cliente , log ) ;
CHECK ( codcf > old_codcf , " Ordinamento clienti errato! " ) ;
2010-09-01 15:47:38 +00:00
//aggiorna old_codcf in modo da poter controllare i contratti solo al cambio codcf
old_codcf = codcf ;
const int n_contratti = find_contratti_cliente ( codcf , mask , contratti_cliente ) ;
if ( n_contratti = = 0 )
{
TString msg ;
msg < < " Il cliente " < < codcf < < " non ha un contratto premi valido nel periodo di elaborazione selezionato ma ha fatture. " ;
log . log_error ( msg ) ;
}
}
if ( contratti_cliente . items ( ) > 0 )
{
//se ha trovato uno o pi<70> contratti validi nel periodo passa alla elaborazione dei documenti del cliente
2010-09-27 14:30:54 +00:00
TDocumento * curr_doc = new TDocumento ( fatture . cursor ( ) - > curr ( ) ) ;
2010-09-01 15:47:38 +00:00
//elabora il documento corrente aggiornando le somme restituite sui contratti validi
2010-09-13 13:39:46 +00:00
if ( elabora_contratti ( * curr_doc , contratti_cliente ) )
2010-09-01 15:47:38 +00:00
documenti_cliente . add ( curr_doc ) ;
else
delete ( curr_doc ) ;
}
} //for (bool ok = recset.move_first()...
2010-09-27 14:30:54 +00:00
//generazione NAC dell'ultimo cliente (una per contratto cliente)
2010-09-01 15:47:38 +00:00
genera_nac ( mask , contratti_cliente , documenti_cliente , log ) ;
2010-09-13 13:39:46 +00:00
//se elaborazione definitiva -> cambia lo stato ai documenti di vendita elaborati, mettendolo uguale..
//..a quello deciso in configurazione
const bool definitivo = mask . get_bool ( F_DEFINITIVO ) ;
if ( definitivo )
{
TConfig config ( CONFIG_DITTA , " ha " ) ;
const TString & stato_finale = config . get ( " StatoFinFatt " ) ;
FOR_EACH_ARRAY_ITEM ( documenti_cliente , r , riga )
{
TDocumento & fattura = * ( TDocumento * ) riga ;
fattura . put ( DOC_STATO , stato_finale ) ;
fattura . rewrite ( ) ;
}
}
2010-09-01 15:47:38 +00:00
}
//metodo di alto livello con i punti principali del programma (come da analisi...)
void THardy_elab_docs : : elabora ( const TMask & mask )
{
//1) eventuale accoppamento di tutti i documenti provvisori creati con precedenti elaborazioni precedenti
int nac_killed = 0 ;
if ( mask . get_bool ( F_KILLPROVV ) )
nac_killed = kill_provv_nac ( mask ) ;
//log report con segnalazioni sui clienti trattati (bene o male)
TLog_report log ( " Sintesi elaborazione " ) ;
log . kill_duplicates ( ) ;
log . log ( 0 , " " ) ;
//2) recordset ordinato codag-codcf-numdoc con tutti i docs che soddisfano i parametri dell'utente
// ---------------------------------------------------------------------------------------------
TISAM_recordset recset ( " " ) ;
const long items = genera_recordset ( mask , recset ) ;
if ( items = = 0 )
{
log . log ( 1 , " Non esistono documenti di vendita che soddisfino i parametri selezionati! Ritenta sarai pi<70> fortunato! " ) ;
}
//3) elaborazione documenti e contratti, generazione NAC, salvataggi
// ---------------------------------------------------------------
elabora_documenti ( mask , recset , log ) ;
//3) scrittura log
// -------------
log . print_or_preview ( ) ;
}
void THardy_elab_docs : : main_loop ( )
{
THardy_elab_docs_mask mask ;
while ( mask . run ( ) = = K_ENTER )
{
elabora ( mask ) ;
}
}
bool THardy_elab_docs : : create ( )
{
open_files ( LF_DOC , LF_RIGHEDOC , 0 ) ;
return TSkeleton_application : : create ( ) ;
}
int ha0500 ( int argc , char * argv [ ] )
{
2010-09-27 14:30:54 +00:00
THardy_elab_docs elabapp ;
elabapp . run ( argc , argv , TR ( " Generazione NAC " ) ) ;
return 0 ;
2010-09-01 15:47:38 +00:00
}