Visualizzazione dei risultati da 1 a 10 su 10
  1. #1
    Utente di HTML.it
    Registrato dal
    Dec 2008
    Messaggi
    121

    Operazioni con sconto e iva

    Saluti a tutti!

    In pratica, ho questo problema e sto diventano come la faccina ->

    Ho un database (ma và?) con diverse tabelle (nah, e sei un genio!) che riassumo così:

    codice:
    Tabella clienti:
    
    idCliente 
    blablabla
    
    Tabella documenti:
    idDocumento
    blablabla
    
    Tabella articoliDocumenti:
    idArticoloDocumento
    valore_unitario
    sconto
    qty
    iva
    
    Tabella docArtDoc
    idDocArtDoc
    idArticoloDocumento
    idDocumento
    Credo sia chiaro a tutti. Insomma, dovrei selezionare i dati principali del documento, poi sommare i dati di ogni singolo articoloDocumento per ottenerne un totale... forse è meglio se spiego pseudomatematicamente.
    Questo è quello che vorrei facesse la query, in pratica: facciamo finta di avere una griglia tipo la seguente...
    codice:
    Numero documento | Data documento | Totale documento 
              1           ieri                     1.000
              2          oggi                    1.953
    Dunque, io avevo preparato questa query:

    codice:
    SELECT documenti. * ,  SUM(valore_unitario - ( valore_unitario * sconto /100 ) + ( valore_unitario * iva /100 ) * qty)  AS sommaTotale
    FROM articoliDocumenti, docartdoc, clienti, documenti
    WHERE documenti.idCliente = clienti.idCliente
    AND docArtDoc.idDocumento = documenti.idDocumento
    AND articoliDocumenti.idArticoloDocumento = docArtDoc.idArticoloDocumento
    AND clienti.idCliente =1
    che, ovviamente, speravo restituisse tutti i documenti relativi ad idCliente dove per ogni riga
    veniva restituito il totale derivante dalla moltiplicazione del prezzo del singolo prodotto, sottratto lo sconto e aggiunta l'iva, per qty (la quantità). Ho anche provato con questa subquery:

    codice:
    SELECT documenti. * , (SELECT SUM(valore_unitario - ( valore_unitario * sconto /100 ) + ( valore_unitario * iva /100 ) * qty) FROM articoliDocumenti)  AS sommaTotale
    FROM articoliDocumenti, docartdoc, clienti, documenti
    WHERE documenti.idCliente = clienti.idCliente
    AND docArtDoc.idDocumento = documenti.idDocumento
    AND articoliDocumenti.idArticoloDocumento = docArtDoc.idArticoloDocumento
    AND clienti.idCliente =1
    ma chiaramente senza successo. Il set restituito è abnormemente zeppo di risultati uguali. Aggiungere la clausola DISTINCT non apporta alcun beneficio. Preciso che docArtDoc non è altro che una tabella che contiene i riferimenti per collegare articoliDocumenti a Documenti.

    Ragazzi sono giorni che sto così -> e non riesco manco a
    Eppure credo che sia una banalità!!!

  2. #2
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    1,469
    cominciamo col dire che... non funzionerà mai, perchè ci sono gli euro-arrotondamenti che sono qualcosa di veramente devastante (a dir poco)
    ---
    per il resto ti suggerisco di preparare un db di prova, dumparlo, caricalo da qualche parte (se non è gigante pure qui) e via

  3. #3
    Utente di HTML.it
    Registrato dal
    Dec 2008
    Messaggi
    121
    A dire la verità, ho fatto qualche passetto avanti... così:

    codice:
    SELECT documenti. * , TRUNCATE( SUM(
    
    (valore_unitario - (valore_unitario*(sconto)/100) + ( (valore_unitario- (valore_unitario*(sconto)/100)) *(iva)/100)) * qty) ,2)   AS sommaTotale
    FROM articoliDocumenti, docartdoc, clienti, documenti
    WHERE documenti.idCliente = clienti.idCliente
    AND docArtDoc.idDocumento = documenti.idDocumento
    AND articoliDocumenti.idArticoloDocumento = docArtDoc.idArticoloDocumento
    AND clienti.idCliente =1 AND tipoDocumento = 0 GROUP BY idDocumento
    anche se... a volte restituisce null, altre volte dati sbagliati. Non vorrei aver sbagliato qualcosa con le parentesi... in realtà non mi è chiaro aritmeticamente il passaggio.
    Intendo dire che l'iva va calcolata sul valore_unitario già scontato. Per cui, si tratterebbe di fare questi passaggi:
    codice:
    1) valore_unitario * sconto / 100
    
    2) valore_unitario - il risultato del punto 1 e cioè
    valore_unitario - (valore_unitario * sconto / 100)
    3) calcolare e aggiungere l'iva al risultato del punto 2, ovvero
    ((valore_unitario - (valore_unitario * sconto / 100)) * iva / 100) + valore_unitario
    4) moltiplicare tutto per la quantità, e cioè: 
    (((valore_unitario - (valore_unitario * sconto / 100)) * iva / 100) + valore_unitario) * qty
    Corretto? Non lo so... a volte mi da null e altre volte sclera con i risultati.

    Franzauker, mi spieghi cosa intendi per euro-arrotondamenti devastanti? E, soprattutto, perché non funzionerà mai? Più tardi preparo il dump e lo posto qui, non è niente di colossale, faccio una versione minimal Grazie!

  4. #4
    Utente di HTML.it
    Registrato dal
    Dec 2008
    Messaggi
    121
    Franzauker, ecco qui il dump in allegato! Vediamo se riusciamo a venirne fuori!!!

    codice:
    CREATE DATABASE testDB;
    USING testDB;
    CREATE TABLE IF NOT EXISTS `articolidocumenti` (
      `idArticoloDocumento` int(50) NOT NULL AUTO_INCREMENT,
      `ean` varchar(255) DEFAULT NULL,
      `descrizione` text NOT NULL,
      `qty` int(5) NOT NULL,
      `valore_unitario` decimal(10,2) NOT NULL,
      `sconto` decimal(10,2) DEFAULT '0.00',
      `iva` decimal(10,2) DEFAULT '0.00',
      PRIMARY KEY (`idArticoloDocumento`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=latin1;
    
    
    INSERT INTO `articolidocumenti` (`idArticoloDocumento`, `ean`, `descrizione`, `qty`, `valore_unitario`, `sconto`, `iva`) VALUES
    (1, 'ean1', 'articolo1', 1, 120.00, 0.00, 20.00),
    (2, 'ean2', 'articolo2', 1, 12.90, 10.00, 20.00),
    (3, 'ean3', 'articolo3', 1, 99.00, 0.00, 10.00),
    (4, 'ean4', 'articolo4', 1, 358.33, 15.00, 20.00),
    (5, 'ean5', 'articolo5', 1, 0.67, 0.00, 5.00);
    
    
    CREATE TABLE IF NOT EXISTS `clienti` (
      `idCliente` int(10) NOT NULL AUTO_INCREMENT,
      `nome` text,
      `cognome` text,
      PRIMARY KEY (`idCliente`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=latin1;
    
    INSERT INTO `clienti` (`idCliente`, `nome`, `cognome`) VALUES
    (1, 'Mario', 'Rossi');
    
    
    CREATE TABLE IF NOT EXISTS `docartdoc` (
      `idDocArtDoc` int(5) NOT NULL AUTO_INCREMENT,
      `idDocumento` int(5) NOT NULL,
      `idArticoloDocumento` int(50) NOT NULL,
      PRIMARY KEY (`idDocArtDoc`,`idDocumento`,`idArticoloDocumento`),
      KEY `idPreventivo` (`idDocumento`),
      KEY `idArticoloPreventivo` (`idArticoloDocumento`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=latin1;
    
    INSERT INTO `docartdoc` (`idDocArtDoc`, `idDocumento`, `idArticoloDocumento`) VALUES
    (1, 1, 1),
    (2, 1, 2),
    (3, 1, 3),
    (4, 2, 4),
    (5, 2, 5);
    
    CREATE TABLE IF NOT EXISTS `documenti` (
      `idDocumento` int(255) NOT NULL AUTO_INCREMENT,
      `numeroPreventivo` int(255) DEFAULT NULL,
      `dataDocumento` date NOT NULL,
      `tipoDocumento` int(2) DEFAULT NULL,
      `idCliente` int(10) DEFAULT NULL,
      PRIMARY KEY (`idDocumento`),
      KEY `idCliente` (`idCliente`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=latin1;
    
    INSERT INTO `documenti` (`idDocumento`, `numeroPreventivo`, `dataDocumento`, `tipoDocumento`, `idCliente`) VALUES
    (1, 1, '2011-01-07', 0, 1),
    (2, 2, '2011-01-07', 0, 1);
    Niente di così gigantesco, versione ridotta all'osso ma sufficiente!

  5. #5
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    1,469
    domani devo cambiare i dischi a un server; se trovo il tempo ti dò la risposta
    --------
    riguardo agli arrotondamenti euro... non esiste una funzione per seguire la regola per l'arrotondamento dei valori.

    questo implica che i calcoli di iva, imponibile etc sono veramente complicati (su mysql), qualora non si abbia il supporto del linguaggio (o non si scriva una relativa stored procedure)

  6. #6
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    1,469
    Allora, al netto degli arrotondamenti (che son devastanti, lo ribadisco)
    questo ti dà i totali (che penso siano quelli che cerchi)

    select documenti.iddocumento,sum(qty*valore_unitario) as imponibile_lordo,
    sum(qty*valore_unitario*(100-sconto)/100) as imponibile_scontato,
    sum(qty*valore_unitario*(100-sconto)/100*iva/100) as importo_iva,
    sum(qty*valore_unitario*(100-sconto)/100*(1+iva/100)) as totale_ivato
    from documenti,docartdoc, articolidocumenti
    where documenti.iddocumento=docartdoc.iddocumento
    and docartdoc.idarticolodocumento=articolidocumenti.id articolodocumento
    group by iddocumento

    personalmente ritengo che la modellazione che hai fatto sia piuttosto lontana da come si fa normalmente per i normali documenti testata-righe; c'è un motivo particolare per cui lo vuoi tenere così (normalizzazione?) o no?

    è quantomeno auspicabile de-normalizzare lo schema ed inserire tanti bei campettini con i valori, ognuno dei quali euro-arrotondato

    ciò ti consente di fare query con un solo join (enormemente più veloce), o anche nessun join del tutto (tenendo i totali nella testata)

    inoltre hai anche la possibilità di avere un controllo tra le righe ed i totali, utile per evitare che problemi sul db ti seghino via definitivamente informazioni preziose.

    supponi che una delle righe di docartdoc sparisca: il tuo documento sarà modificato per sempre e non potrai in alcun modo capire che è stato alterato.

    questo motivo, da solo, è generalmente sufficiente (parlo di gestionali "veri") a suggerire approcci diversi.

    buonanotte ci aggiorniamo se ti servono altre info

  7. #7
    Utente di HTML.it
    Registrato dal
    Dec 2008
    Messaggi
    121
    Uhm... tutto fila liscio per l'imponibile_lordo, ma per gli altri valori c'è un problema. La tua query non restituisce il valore esatto (anzi, sembra restituire un valore del tutto incoerente).

    Uso la forma normale per il semplice fatto che non ho idea di come inserire più articoli all'interno dello stesso documento, in quanto il numero degli articoli è, ovviamente, variabile. Per cui non so proprio come fare riferimento alla tabella articoliDocumenti direttamente da documenti, se non ho capito male ciò che intendi. Se poi intendi di schiaffare tutti gli articoli all'interno della tabella documenti, si, sarebbe più semplice, ma avrei una ripetizione di tuple micidiale... se hai suggerimenti sono molto ben accetti!

  8. #8
    Utente di HTML.it
    Registrato dal
    Dec 2008
    Messaggi
    121
    Sorry, colpa mia... in realtà andava fin dall'inizio, solo che avevo dei campi sconto pari a null e quindi non venivano considerati nella computazione totale.
    Resto comunque in attesa di consigli e critiche! :-)

  9. #9
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    1,469
    bhè cominciamo col dire che IL modo non esiste (per modellare i normali documenti fiscali o parafiscali).
    Esistono "tanti" modi diversi, ognuno con pregi e difetti.
    ---
    Il modo "normale" (intendo quello che si usa "nella vita reale") prevede una struttura estremamente semplice, testata-righe (e in realtà totali)

    esempio: tabella documenti

    ser (autoincrementante, questo ci vuole come "puntatore")

    poi una chiave multipla
    anno [ovvio]
    polo_amministrativo [se si gestiscono più aziende]
    tipo_documento [FATura, DDT, CARico, SCArico, PROva...]
    progressivo [il numero del documento, in generale è un numero, ma può essere anche una stringa se ci sono le serie]

    quindi il payload anagrafico

    datadocumento
    codicecliente
    ditta
    indirizzo [ovviamente DEVE essere "denormalizzato" logicamente]
    citta
    provincia
    cap
    codicefiscale
    partitaiva
    (...) dati bancari blablabla

    il payload contabile
    lordo
    sconto
    rimborso
    imponibile
    nonimponibile
    cassaprevidenza
    iva
    totaledocumento
    ritenuta
    abbuoni (...)
    totaledacorrispondere
    flagivadiversa (utile per rendere più semplice i report)

    un po' di flag (booleani, ma tienili come interi 0/1, sempre utili per i report)

    flagsconto
    flagrimborso
    flagiva
    flagcassa
    flagritenuta

    le percentuali

    persconto
    perrimborso
    periva
    percassa
    perritenuta

    ...roba varia...
    luogoconsegna...
    vettore...
    bancaappoggio blablabla
    modalitapagamento
    scadenze

    "incassi"
    dataincasso
    dataanticipo (bancario)
    importoincassato (finora, anche in + tranche, serve per i report)
    importoanticipato


    poi arriviamo alle righe

    idlink: chiave univoca del documento, tipicamente una funzione hash di un pezzo dei dati+random+quello che vuoi
    numerorighe (serve per controllo di quadratura)


    ------------------
    Ok adesso abbiamo la tabella righe

    ser (questo ci vuol sempre)
    idlink: chiave importata da documenti
    ordine: intero che ti servirà per cambiare l'ordine delle righe

    e poi i dati che devono, ovviamente, essere denormalizzati

    codicearticolo
    descrizionearticolo
    unitamisura
    ...
    quantitaimponibile
    scontoimponibile
    rimborsoimponibile
    importoimponibile
    totaleimponibile
    codiceiva
    periva
    totaleivato

    (se è un progetto per professionisti ti serve tutto.
    In realtà potresti farlo con una singola colonna, ma per i report te ne suggerisco 3)

    quantitaspesenonimponibili
    scontospesenonimponibili
    rimborsospesenonimponibili
    importononimponibili
    totalenonimponibili

    quantitaspeseimponibili
    scontospeseimponibili
    rimborsospeseimponibili
    importospeseimponibili
    codiceivasese
    perivaspese
    totalespeseimponibili
    totaleivatospese

    totaleriga


    ---------
    poi normalmente si fa una tabella righetotali
    (praticamente raggruppano i codici IVA coi totalini, serve per il piede del report),
    magari una con le scadenze
    (date ed importi)

    sempre collegati col campo idlink
    ---------

  10. #10
    Utente di HTML.it
    Registrato dal
    Dec 2008
    Messaggi
    121
    Ammazza... non avevo minimamente pensato ad implementare una struttura così. Indubbiamente credo che sia la cosa migliore! Però avrei dovuto pensarlo così sin dall'inizio, cambiare tutto ora è un casino e considerando che mi serve per un "gestionalino" per la mia attività di commerciante e che non sono un "sql-master"... Non appena avrò più tempo libero studierò ben bene come adattare questo "pattern" alle esigenze che (magari!) si presenteranno.
    Lo terrò senz'altro a mente per le prossime realizzazioni, e ti ringrazio moltissimo per la disponibilità dimostrata!

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.