IF OBJECT_ID('contabilizza_documenti') IS NOT NULL
	DROP PROCEDURE contabilizza_documenti
GO

/*
--Esempio

DECLARE @result INT
EXEC dbo.contabilizza_documenti @document_type = 1 
, @from_document_number = 1
, @to_document_number = 1
, @from_document_serie = ''
, @to_document_serie = ''
, @from_document_date = {d '2021-01-01'}
, @to_document_date = {d '2021-12-31'}
, @result = @result
, @result_scartati = @result_scartati

*/
CREATE PROCEDURE contabilizza_documenti
-- parametri
@document_type INT -- -1=tutti, 3=fatture, 4=note di credito, 11=documento commerciale

, @from_document_number INT 
, @to_document_number INT 

, @from_document_serie VARCHAR(2) 
, @to_document_serie VARCHAR(2) 

, @from_document_date DATETIME 
, @to_document_date DATETIME 

, @lock_pratiche BIT 

, @result INT OUTPUT
, @result_scartati INT OUTPUT

AS BEGIN

--DECLARE @document_type INT
--DECLARE @from_document_number INT 
--DECLARE @to_document_number INT 
--DECLARE @from_document_serie VARCHAR(2) 
--DECLARE @to_document_serie VARCHAR(2) 
--DECLARE @from_document_date DATETIME 
--DECLARE @to_document_date DATETIME 
--DECLARE @result INT
--SET @document_type = 3
--SET @from_document_number = 1
--SET @to_document_number = 1
--SET @from_document_date = {d '2021-01-01'}
--SET @to_document_date = {d '2021-12-31'}
--contabilizza_documenti 

-- variabili

DECLARE @cau_cod_default_fattura INT
DECLARE @cau_cod_default_nota_credito INT
DECLARE @cau_cod_default_corrispettivi INT
DECLARE @cnt_id_cassa INT
DECLARE @cnt_tipcnt_id_cassa INT
DECLARE @parcont_pag_cod_fattura_cliente INT


		

SET @result = 0

-- CREA TABELLE TEMPORANEE

IF OBJECT_ID('tempdb..#tipo_documento_da_contabilizzare') IS NOT NULL
	DROP TABLE #tipo_documento_da_contabilizzare

CREATE TABLE #tipo_documento_da_contabilizzare (
	tipdoc_id INT
)


IF OBJECT_ID('tmp_prima_nota_master') IS NOT NULL --SELECT OBJECT_ID('tempdb..#prima_nota')
	DROP TABLE tmp_prima_nota_master

CREATE TABLE tmp_prima_nota_master
(
	pn_id INT IDENTITY PRIMARY KEY NOT NULL

	, pn_registrazione_numero INT NOT NULL
	, pn_registrazione_data DATETIME NOT NULL

	, pn_cau_cod INT NOT NULL -- chiave esterna causale

	, pn_cnt_id_cliente_fornitore INT NULL -- chiave esterna conto cliente/fornitore/null
	, pn_tipcnt_id INT NULL -- chiave esterna tipo conto
	
	, pn_doc_cod VARCHAR(50) NULL
	, pn_pra_cod VARCHAR(50) NULL
	, pn_tipdoc_id INT NULL
	, pn_documento_numero INT NULL
	, pn_documento_serie VARCHAR(10) NULL
	, pn_documento_data DATETIME NULL
	, pn_documento_totale DECIMAL(19, 5) NULL

	, pn_protocollo_numero INT NULL
	, pn_protocollo_serie VARCHAR(10) NULL
	
	, pn_competenza INT NULL
	, pn_competenza_iva DATETIME NULL

	, pn_tipo_registro VARCHAR(1) NULL
	, pn_numero_registro INT NULL

	, pn_pag_cod INT NULL
	
	, pn_note VARCHAR(MAX) NULL

	, pn_row_ver TIMESTAMP
)


IF OBJECT_ID('tmp_prima_nota_dettagli') IS NOT NULL --SELECT OBJECT_ID('tempdb..#prima_nota_dettagli')
	DROP TABLE tmp_prima_nota_dettagli

CREATE TABLE tmp_prima_nota_dettagli
(
	pnd_id INT IDENTITY PRIMARY KEY NOT NULL

	, pnd_numero_riga INT NOT NULL

	, pnd_cau_cod INT NOT NULL -- chiave esterna causale

	, pnd_cnt_id INT NOT NULL -- chiave esterna conto
	, pnd_tipcnt_id INT NULL -- chiave esterna tipo conto

	, pnd_dare	DECIMAL(19, 5) NULL
	, pnd_avere DECIMAL(19, 5) NULL

	-- per le righe iva
	--, pnd_imponibile DECIMAL(19, 5) NULL
	--, pnd_aliquota DECIMAL(9, 4) NULL
	--, pnd_iva_cod INT NULL -- chiave esterna codice iva

	, pnd_flag_partite VARCHAR(1) NULL /* 'C'=Crea, 'S'=Salda, 'A'=Acconto, ' '=Non Gestite, NULL=Non Gestite  */

	, pnd_pn_id INT NOT NULL -- chiave esterna riferimento alla testata

	, pnd_row_ver TIMESTAMP
)

IF OBJECT_ID('tmp_prima_nota_iva') IS NOT NULL --SELECT OBJECT_ID('tempdb..#prima_nota_iva')
	DROP TABLE tmp_prima_nota_iva

CREATE TABLE tmp_prima_nota_iva
(
	pni_id INT IDENTITY PRIMARY KEY NOT NULL
	
	, pni_numero_riga INT NOT NULL

	, pni_imponibile DECIMAL(19, 5) NULL
	, pni_aliquota DECIMAL(9, 4) NULL
	, pni_importo_iva DECIMAL(19, 5) NULL

	, pni_cnt_id_iva INT NULL -- chiave esterna conti (iva)
	, pni_tipcnt_id_iva INT NULL -- chiave esterna tipi_conti (iva)

	, pni_cnt_id_contropartita INT NULL -- chiave esterna questo servirebbe per avere il totale iva compresa per le statistiche per tipologia.
	, pni_tipcnt_id_contropartita INT NULL -- chiave esterna tipi_conti

	, pni_iva_cod INT NOT NULL -- chiave esterna aliquote_iva
	, pni_percentuale_indetraibilita DECIMAL(9, 4) NULL

	, pni_tipo_registro VARCHAR(1) NULL
	, pni_numero_registro INT NULL

	, pni_pn_id INT NOT NULL -- chiave esterna riferimento alla testata di prima nota
)

IF OBJECT_ID('tmp_partite') IS NOT NULL --SELECT OBJECT_ID('tempdb..#partite')
	DROP TABLE tmp_partite

CREATE TABLE tmp_partite
(
	pt_id INT IDENTITY NOT NULL

	, pt_numero VARCHAR(100)

	, pt_data_scadenza DATETIME

	, pt_cnt_id INT NULL
	, pt_tipo_conto VARCHAR(1) NULL /* C=cliente F=fornitore G=generico */
	, pt_conto VARCHAR(50) NULL
	, pt_conto_nome VARCHAR(200) NULL

	, pt_segno VARCHAR(1) NULL /* D o A */

	, pt_importo DECIMAL(19, 4) NULL
	, pt_sum_importo DECIMAL(19, 4) NULL

	, pt_flag_crea_salda VARCHAR(1) NULL /* C=Crea, S=Salda, A=Acconto */

	, pt_totale_abbuono DECIMAL(19, 4) NULL

	/* riferimento al documento */
	, pt_doc_tipo_doc_fisc SMALLINT NULL
	, pt_doc_numero INT NULL
	, pt_doc_alt VARCHAR(10) NULL
	, pt_doc_data DATETIME NULL
	, pt_doc_totale DECIMAL(19, 4) NULL

	, ban_cod_appoggio INT NULL
	, bancar_id INT NULL

	, doc_cod VARCHAR(36) NULL

	, tpag_id INT NULL

	, pt_row_ver TIMESTAMP

	, pt_pn_id INT NULL -- riferimento alla prima nota

	, pt_pnd_id INT NULL -- riferimento al dettaglio di prima nota a cui questa riga appartiene

)


-- tabelle di link delle identità tra le tabelle temporanee e quelle definitive
-- per usate nella copia delle tabelle child

-- tabella di linkage prima_nota_master e tmp_prima_nota_master
IF OBJECT_ID('tempdb..#prima_nota_master_linkage') IS NOT NULL --SELECT OBJECT_ID('tempdb..#prima_nota_iva_linkage')
	DROP TABLE #prima_nota_master_linkage

CREATE TABLE #prima_nota_master_linkage
(
	pnl_tpn_id INT NOT NULL PRIMARY KEY -- pn_id della tabella temporanea #prima_nota_master
	, pnl_pn_id INT NOT NULL -- pn_id della tabella prima_nota_master delle righe inserite dal comando MERGE
)


-- tabella di linkage #prima_nota_dettagli_linkage e prima_nota_master_linkage
IF OBJECT_ID('tempdb..#prima_nota_dettagli_linkage') IS NOT NULL
	DROP TABLE #prima_nota_dettagli_linkage

CREATE TABLE #prima_nota_dettagli_linkage
(
	pndl_tpnd_id INT NOT NULL PRIMARY KEY -- pnd_id della tabella temporanea #prima_nota_dettagli
	, pndl_pnd_id INT NOT NULL -- pnd_id della tabella prima_nota_dettagli delle righe inserite dal comando MERGE
)



-- inizio procedura

-- prendi le causali predefinite
SELECT
		@cau_cod_default_fattura = parcont_cau_cod_fattura_cliente
		, @cau_cod_default_nota_credito = parcont_cau_cod_nota_di_credito_cliente
		/*, @cau_cod_default_corrispettivi = parcont_cau_cod_corrispettivi*/
	FROM parametri_contabilita

-- prendi il conto cassa
SELECT
		@cnt_id_cassa = cnt_id, @cnt_tipcnt_id_cassa = cnt_tipcnt_id
	FROM parametri_contabilita
	INNER JOIN conti ON parcont_conto_cassa = conti.cnt_codice

-- prendi il pagamento di default della fattura
SELECT @parcont_pag_cod_fattura_cliente = parcont_pag_cod_fattura_cliente FROM parametri_contabilita


-- gestione filtri

-- imposta i tipi di documento da contabilizzare
IF @document_type = -1 OR @document_type IS NULL -- tutti
	INSERT INTO #tipo_documento_da_contabilizzare (tipdoc_id) VALUES
		(2) --'Corrispettivi'
		, (3) --'Fattura'
		, (4) --'Nota di credito'
		, (11) --'Documento Commerciale'
ELSE
	INSERT INTO #tipo_documento_da_contabilizzare (tipdoc_id) VALUES (@document_type)

IF NOT EXISTS(SELECT * FROM #tipo_documento_da_contabilizzare)
	INSERT INTO #tipo_documento_da_contabilizzare (tipdoc_id) VALUES
		(2) --'Corrispettivi'
		, (3) --'Fattura'
		, (4) --'Nota di credito'
		, (11) --'Documento Commerciale'


IF @from_document_number IS NULL
	SET @from_document_number = 0

IF @to_document_number IS NULL
	SET @to_document_number = 999999999

IF @from_document_serie IS NULL
	SET @from_document_serie = ''

IF @to_document_serie IS NULL
	SET @to_document_serie = 'ZZ' -- if 'Z' COLLATE Latin1_General_CS_AS > 'z' print '1' else print '2'

IF @from_document_date IS NULL
	SET @from_document_date = '17530101'

IF @to_document_date IS NULL
	SET @to_document_date = '99991231'

-- In caso di errore, blocca la transazione e la rende uncommittable.
-- Se fosse OFF (il default) sarebbe fatta la ROLLBACK solo dei comandi falliti
-- e non di tutta la transazione.
SET XACT_ABORT ON

-- Variabile usata per eseguire la RAISERROR fuori dalla CATCH, in modo da entrare nella  
-- catch del chiamante
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
DECLARE @ErrorLine INT;
DECLARE @bError AS BIT
SET @bError = 0

BEGIN TRY
	BEGIN TRANSACTION


-- inserisci rige master

INSERT INTO tmp_prima_nota_master (
		pn_registrazione_numero
		, pn_registrazione_data
		, pn_cau_cod
		, pn_cnt_id_cliente_fornitore
		, pn_tipcnt_id
		, pn_doc_cod
		, pn_pra_cod
		, pn_tipdoc_id
		, pn_documento_numero
		, pn_documento_serie
		, pn_documento_data
		, pn_documento_totale
		, pn_competenza
		, pn_competenza_iva
		, pn_tipo_registro
		, pn_numero_registro
		, pn_pag_cod
	)
	SELECT

			0 registrazione_numero
			, doc_data
			-- causale specificata o quella di default in base al tipo di documento		
			, causali.cau_cod -- CASE WHEN cau_cod IS NOT NULL THEN cau_cod ELSE CASE doc_super_tipo WHEN 3 THEN @cau_cod_default_fattura WHEN 4 THEN @cau_cod_default_nota_credito WHEN 11 THEN @cau_cod_default_corrispettivi END END
			, CASE WHEN documenti.doc_bound = 1 THEN clienti.cli_cnt_id ELSE CASE WHEN intestatari.cli_cnt_id IS NOT NULL THEN intestatari.cli_cnt_id ELSE clienti.cli_cnt_id END END cli_cnt_id
			, cnt_tipcnt_id
			, doc_cod
			, documenti.pra_cod
			, doc_super_tipo
			, doc_numero
			, doc_num_alt
			, doc_data
			, doc_tot_generale
			, YEAR(doc_data) competenza
			, doc_data
			, tri_tipo_registro
			, cau_numero_registro
			, CASE WHEN documenti.pag_cod IS NOT NULL THEN documenti.pag_cod ELSE CASE WHEN CASE WHEN documenti.doc_bound = 1 THEN clienti.pag_cod ELSE intestatari.pag_cod END IS NOT NULL THEN CASE WHEN documenti.doc_bound = 1 THEN clienti.pag_cod ELSE intestatari.pag_cod END ELSE CASE doc_super_tipo WHEN 3/*fattura*/ THEN @parcont_pag_cod_fattura_cliente WHEN 4/*nota di credito*/ THEN NULL WHEN 11/*documento commerciale*/ THEN NULL END END END pag_cod

		FROM documenti
		INNER JOIN pratiche ON documenti.pra_cod = pratiche.pra_cod
		INNER JOIN veicoli ON pratiche.vei_cod = veicoli.vei_cod
		INNER JOIN clienti clienti ON veicoli.cli_cod = clienti.cli_cod
		INNER JOIN conti ON cli_cnt_id = cnt_id
		INNER JOIN causali ON causali.cau_cod = CASE WHEN documenti.cau_cod IS NOT NULL THEN documenti.cau_cod ELSE CASE doc_super_tipo WHEN 3 THEN @cau_cod_default_fattura WHEN 4 THEN @cau_cod_default_nota_credito WHEN 11 THEN @cau_cod_default_corrispettivi END END
		--CROSS JOIN parametri_contabilita
		LEFT JOIN parti_x_documenti ON doc_cod = parxdoc_cod_u
		LEFT JOIN clienti intestatari ON parti_x_documenti.cli_cod = intestatari.cli_cod

		WHERE
			(
				doc_super_tipo = 3 -- fatture
				OR doc_super_tipo = 4 -- nota di credito
				OR doc_super_tipo = 11 -- documento commerciale
			)
			AND doc_super_tipo IN (SELECT tipdoc_id FROM #tipo_documento_da_contabilizzare)
			AND doc_numero >= @from_document_number
			AND doc_numero <= @to_document_number
			AND doc_num_alt >= @from_document_serie
			AND doc_num_alt <= @to_document_serie
			AND doc_data >= @from_document_date
			AND doc_data <= @to_document_date
			AND doc_contabil = 0 -- documenti non contabilizzati

------------------------------------------------------------------------------------------------------------------------
-- Escludiamo da Prima nota master eventuali documenti appartenenti a pratiche bloccate da altro utente
------------------------------------------------------------------------------------------------------------------------

IF @lock_pratiche = 1
BEGIN
		IF	OBJECT_ID('tempdb..#documenti_scartati') IS NOT NULL
		BEGIN
			DROP TABLE #documenti_scartati;
		END

		CREATE TABLE #documenti_scartati
		(
			doc_cod NVARCHAR(36) COLLATE database_default NOT NULL,
			pra_cod NVARCHAR(36) COLLATE database_default NOT NULL
		);

		IF	OBJECT_ID('tempdb..#pratiche_bloccate') IS NOT NULL
		BEGIN
			DROP TABLE #pratiche_bloccate
		END

		CREATE TABLE #pratiche_bloccate
		(
			pra_cod NVARCHAR(36) COLLATE database_default NOT NULL
		);

		-- blocca le pratiche
		INSERT INTO #pratiche_bloccate SELECT pra_cod FROM pratiche WITH (UPDLOCK, ROWLOCK, READPAST) WHERE pra_cod IN (SELECT pn_pra_cod FROM tmp_prima_nota_master)

		-- la differenza tra tmp_prima_nota_master e le pratiche bloccate sono le pratiche bloccate da altri utenti
		INSERT INTO #documenti_scartati (doc_cod, pra_cod) SELECT pn_doc_cod, pn_pra_cod FROM tmp_prima_nota_master WHERE pn_pra_cod NOT IN (SELECT pra_cod FROM #pratiche_bloccate)

		-- cancella da tmp_prima_nota_master i documenti delle pratiche bloccate da altri utenti
		DELETE tmp_prima_nota_master WHERE pn_doc_cod IN (SELECT doc_cod FROM #documenti_scartati)
END

-- Fine esclusione documenti utilizzati da altro utente ---------------------------------------------------------------------------------------------------


-- RIGHE DETTAGLI DI PRIMA NOTA (prima_nota_dettagli)

-- riga cliente/cassa
INSERT INTO tmp_prima_nota_dettagli
	(
		pnd_numero_riga
		, pnd_cau_cod
		, pnd_cnt_id
		, pnd_tipcnt_id
		, pnd_dare
		, pnd_avere
		, pnd_flag_partite
		, pnd_pn_id
	)
	SELECT
			1 pnd_numero_riga
			, pn_cau_cod
			, CASE WHEN pn_tipdoc_id = 2/*ricevuta*/ OR pn_tipdoc_id = 11/*documento commerciale*/ THEN /*cassa*/@cnt_id_cassa ELSE pn_cnt_id_cliente_fornitore END
			, CASE WHEN pn_tipdoc_id = 2/*ricevuta*/ OR pn_tipdoc_id = 11/*documento commerciale*/ THEN /*cassa*/@cnt_tipcnt_id_cassa ELSE pn_tipcnt_id END 
			, /* dare */ CASE WHEN pn_tipdoc_id = 2/*ricevuta*/ OR pn_tipdoc_id = 3/*fattura*/ OR pn_tipdoc_id = 11/*documento commerciale*/ THEN pn_documento_totale ELSE 0 END
			, /* avere */CASE WHEN pn_tipdoc_id = 4/*nota di credito*/ THEN pn_documento_totale ELSE 0 END
			, cau_gestione_partite
			, pn_id
		FROM tmp_prima_nota_master
		INNER JOIN causali ON
			cau_cod = pn_cau_cod


-- riga iva vendite
INSERT INTO tmp_prima_nota_dettagli
	(
		pnd_numero_riga
		, pnd_cau_cod
		, pnd_cnt_id
		, pnd_tipcnt_id
		, pnd_dare
		, pnd_avere
		, pnd_pn_id
	)
	SELECT
			2 pnd_numero_riga
			, pn_cau_cod
			, cau_cnt_id_iva -- conto iva della causale
			, 4 -- tipo conto iva
			, /* dare */CASE WHEN pn_tipdoc_id = 4/*nota di credito*/ THEN doc_tot_imposta ELSE 0 END
			, /* avere */ CASE WHEN pn_tipdoc_id = 2/*ricevuta*/ OR pn_tipdoc_id = 3/*fattura*/ OR pn_tipdoc_id = 11/*documento commerciale*/ THEN doc_tot_imposta ELSE 0 END
			, pn_id
		FROM tmp_prima_nota_master
		INNER JOIN documenti ON
			pn_doc_cod = doc_cod
		INNER JOIN causali ON
			pn_cau_cod = causali.cau_cod



-- righe ricavi
INSERT INTO tmp_prima_nota_dettagli
	(
		pnd_numero_riga
		, pnd_cau_cod
		, pnd_cnt_id
		, pnd_tipcnt_id
		, pnd_dare
		, pnd_avere
		, pnd_pn_id
	)
	SELECT
			0 pnd_numero_riga
			, pn_cau_cod
			, cnt_id
			, cnt_tipcnt_id
			, /* dare */CASE WHEN pn_tipdoc_id = 4/*nota di credito*/ THEN totcat_imponibile ELSE 0 END
			, /* avere */ CASE WHEN pn_tipdoc_id = 2/*ricevuta*/ OR pn_tipdoc_id = 3/*fattura*/ OR pn_tipdoc_id = 11/*documento commerciale*/ THEN totcat_imponibile ELSE 0 END
			, pn_id
		FROM tmp_prima_nota_master
		INNER JOIN totali_x_cat ON
			pn_doc_cod = totali_x_cat.doc_cod
		INNER JOIN categorie ON
			totali_x_cat.cat_cod = categorie.cat_cod
		INNER JOIN conti ON
			categorie.cat_cnt_id = cnt_id





-- RIGHE DETTAGLI IVA (prima_nota_iva)
INSERT INTO tmp_prima_nota_iva
	(
		pni_numero_riga
		, pni_imponibile
		, pni_aliquota
		, pni_importo_iva
		, pni_cnt_id_iva
		, pni_tipcnt_id_iva
		, pni_cnt_id_contropartita
		, pni_tipcnt_id_contropartita
		, pni_iva_cod
		, pni_percentuale_indetraibilita
		, pni_tipo_registro
		, pni_numero_registro
		, pni_pn_id
	)
	SELECT
			0 pni_numero_riga
			, totiva_imponibile
			, iva_aliq
			, totiva_imposta
			, cau_cnt_id_iva
			, 4 -- tipo conto
			, NULL -- pni_cnt_id_contropartita
			, NULL -- pni_tipcnt_id_contropartita
			, aliquote_iva.iva_cod
			, iva_percentuale_indetraibilita
			, tri_tipo_registro
			, cau_numero_registro
			, pn_id
		FROM tmp_prima_nota_master
		INNER JOIN totali_x_iva ON
			pn_doc_cod = doc_cod
		INNER JOIN causali ON
			pn_cau_cod = cau_cod
		INNER JOIN aliquote_iva ON
			totali_x_iva.iva_cod = aliquote_iva.iva_cod




-- caso iva split payment

-- storna l'iva dal conto cliente
INSERT INTO tmp_prima_nota_dettagli
	(
		pnd_numero_riga
		, pnd_cau_cod
		, pnd_cnt_id
		, pnd_tipcnt_id
		, pnd_dare
		, pnd_avere
		, pnd_pn_id
	)
	SELECT
			0 pnd_numero_riga
			, pn_cau_cod
			, pn_cnt_id_cliente_fornitore
			, pn_tipcnt_id
			, /* dare */CASE WHEN pn_tipdoc_id = 4/*nota di credito*/ THEN doc_tot_imposta ELSE 0 END
			, /* avere */ CASE WHEN pn_tipdoc_id = 3/*fattura*/ THEN doc_tot_imposta ELSE 0 END
			, pn_id
		FROM tmp_prima_nota_master
		INNER JOIN documenti ON
			pn_doc_cod = doc_cod
		INNER JOIN causali ON
			pn_cau_cod = causali.cau_cod
		WHERE
			cau_split_payment = 1
			AND (
				pn_tipdoc_id = 3/*fattura*/
				OR pn_tipdoc_id = 4/*nota di credito*/
			)


-- storna l'iva dal conto iva vendite
INSERT INTO tmp_prima_nota_dettagli
	(
		pnd_numero_riga
		, pnd_cau_cod
		, pnd_cnt_id
		, pnd_tipcnt_id
		, pnd_dare
		, pnd_avere
		, pnd_pn_id
	)
	SELECT
			0 pnd_numero_riga
			, pn_cau_cod
			, cau_cnt_id_iva -- conto iva della causale
			, 4 -- tipo conto iva
			, /* dare */ CASE WHEN pn_tipdoc_id = 3/*fattura*/ THEN doc_tot_imposta ELSE 0 END
			, /* avere */CASE WHEN pn_tipdoc_id = 4/*nota di credito*/ THEN doc_tot_imposta ELSE 0 END
			, pn_id
		FROM tmp_prima_nota_master
		INNER JOIN documenti ON
			pn_doc_cod = doc_cod
		INNER JOIN causali ON
			pn_cau_cod = causali.cau_cod
		WHERE
			cau_split_payment = 1
			AND (
				pn_tipdoc_id = 3/*fattura*/
				OR pn_tipdoc_id = 4/*nota di credito*/
			)



-- numerazione delle righe dei dettagli prima nota e iva

-- numera le righe dei dettagli
UPDATE tmp_prima_nota_dettagli
	SET
		pnd_numero_riga = numero_riga
	FROM tmp_prima_nota_dettagli
	INNER JOIN (
		SELECT
				pnd_id id
				, ROW_NUMBER() OVER(PARTITION BY pnd_pn_id ORDER BY pnd_id ASC) numero_riga
			FROM tmp_prima_nota_dettagli
	) numbered_prima_nota_dettagli ON
		pnd_id = id

-- numera le righe dei dettagli iva
UPDATE tmp_prima_nota_iva
	SET
		pni_numero_riga = numero_riga
	FROM tmp_prima_nota_iva
	INNER JOIN (
		SELECT
				pni_id id
				, ROW_NUMBER() OVER(PARTITION BY pni_pn_id ORDER BY pni_id ASC) numero_riga
			FROM tmp_prima_nota_iva
	) numbered_prima_nota_iva ON
		pni_id = id





-- CREAZIONE PARTITE
INSERT INTO tmp_partite
	(
		pt_numero
		, pt_data_scadenza
		, pt_cnt_id
		, pt_tipo_conto /* C=cliente F=fornitore G=generico */
		, pt_conto
		, pt_conto_nome
		, pt_segno /* D o A */
		, pt_importo
		, pt_sum_importo
		, pt_flag_crea_salda /* C=Crea, S=Salda, A=Acconto */
		, pt_totale_abbuono
		/* riferimento al documento */
		, pt_doc_tipo_doc_fisc
		, pt_doc_numero
		, pt_doc_alt
		, pt_doc_data
		, pt_doc_totale
		, ban_cod_appoggio
		, bancar_id
		--, doc_cod
		, tpag_id
		, pt_pn_id -- riferimento alla prima nota
		, pt_pnd_id -- riferimento al dettaglio di prima nota a cui questa riga appartiene
	)
	SELECT
			CAST(YEAR(pn_documento_data) as VARCHAR) + '/' + REPLICATE('0', 10 - LEN(CAST(pn_documento_numero AS VARCHAR))) + CAST(pn_documento_numero AS VARCHAR) pt_numero
			, dbo.due_date(dbo.add_due_days(pn_documento_data, ratpag_giorni_scadenza), ratpag_fine_scadenza, ratpag_giorno_fisso) pt_data_scadenza
			, pn_cnt_id_cliente_fornitore pt_cnt_id
			, CASE pn_tipcnt_id WHEN 2/*Clienti*/ THEN 'C' WHEN 3/*Fornitori*/ THEN 'F' ELSE 'G' END pt_tipo_conto /* C=cliente F=fornitore G=generico */
			, cnt_codice pt_conto
			, cnt_descr pt_conto_nome
			, CASE WHEN pn_tipdoc_id = 4/*nota di credito*/ THEN 'A' ELSE 'D' END --pt_segno /* D o A */
			, ROUND(CASE WHEN sum_ratpag_scalare_netto = 0 THEN 0 ELSE (doc_tot_imponibile * ratpag_scalare_netto / sum_ratpag_scalare_netto) END + CASE WHEN sum_ratpag_scalare_iva = 0 THEN 0 ELSE (doc_tot_imposta * ratpag_scalare_iva / sum_ratpag_scalare_iva) END, 2) pt_importo
			, CASE WHEN sum_ratpag_scalare_netto = 0 THEN 0 ELSE doc_tot_imponibile END + CASE WHEN sum_ratpag_scalare_iva = 0 THEN 0 ELSE doc_tot_imposta END
			, 'C' --pt_flag_crea_salda /* C=Crea, S=Salda, A=Acconto */
			, 0 --pt_totale_abbuono
			/* riferimento al documento */
			, pn_tipdoc_id pt_doc_tipo_doc_fisc
			, pn_documento_numero
			, pn_documento_serie
			, pn_documento_data
			, pn_documento_totale
			, NULL
			, NULL
			--, pn_doc_cod
			, rate_pagamenti.tpag_id
			, pn_id -- riferimento alla prima nota
			, pnd_id -- riferimento alla riga di prima nota
		FROM tmp_prima_nota_master
		INNER JOIN documenti ON
			pn_doc_cod = doc_cod
			--pn_tipdoc_id = doc_super_tipo
			--AND pn_documento_numero = doc_numero
			--AND pn_documento_serie = doc_num_alt
			--AND pn_documento_data = doc_data
		INNER JOIN causali ON
			pn_cau_cod = causali.cau_cod
		INNER JOIN pagamenti ON
			pn_pag_cod = pagamenti.pag_cod
		INNER JOIN rate_pagamenti ON
			pagamenti.pag_cod = rate_pagamenti.pag_cod
		INNER JOIN (SELECT pag_cod, SUM(ratpag_scalare_iva) sum_ratpag_scalare_iva, SUM(ratpag_scalare_netto) sum_ratpag_scalare_netto FROM rate_pagamenti GROUP BY pag_cod) scalari ON
			pagamenti.pag_cod = scalari.pag_cod
		INNER JOIN conti conti_clienti ON
			pn_cnt_id_cliente_fornitore = cnt_id
		INNER JOIN tmp_prima_nota_dettagli ON
			pnd_pn_id = pn_id
			AND pnd_cnt_id = pn_cnt_id_cliente_fornitore
			AND pnd_flag_partite = 'C'
		WHERE
			cau_gestione_partite = 'C' -- crea partite
			-- in teoria anche il conto deve avere la gestione partite. quando sarà gestito occorre controllarlo



-- se per via degli arrotondamenti ai centesimi il totale documento <> dalla somma delle rate la differenza viene applicata all'ultima rata
UPDATE tmp_partite
	SET
		pt_importo = pt_importo - diff
	FROM tmp_partite
	INNER JOIN (
		-- registrazioni con differenze partite
		SELECT
				pn_id
				, diff
			FROM (
				SELECT
						pn_id
						, sum_pt_importo - pt_sum_importo diff
					FROM tmp_prima_nota_master
					INNER JOIN (
						SELECT
								pt_pn_id sum_pt_pn_id
								, pt_sum_importo
								, SUM(pt_importo) sum_pt_importo
							FROM tmp_partite
							GROUP BY
								pt_pn_id
								, pt_sum_importo
								) sum_partite ON
						pn_id = sum_pt_pn_id
				) square_off
			WHERE
				diff <> 0
	) differenze ON
		pt_pn_id = pn_id
	WHERE
		pt_id IN (
			-- identificativi delle ultima riga delle partite la cui somma nn quadra con il totale
			SELECT
					MAX(pt_id) pt_id
					--, pt_pn_id
				FROM tmp_partite
				WHERE
					pt_pn_id IN
						(
							SELECT
									pn_id
								FROM (
									SELECT
											pn_id
											, sum_pt_importo - pt_sum_importo diff
										FROM tmp_prima_nota_master
										INNER JOIN (
											SELECT
													pt_pn_id sum_pt_pn_id
													, pt_sum_importo
													, SUM(pt_importo) sum_pt_importo
												FROM tmp_partite
												GROUP BY
													pt_pn_id
													, pt_sum_importo
													) sum_partite ON
											pn_id = sum_pt_pn_id
									) square_off
								WHERE
									diff <> 0
						)
				GROUP BY
					pt_pn_id
		)


-- copia finale delle tabelle temporanee

-- prima_nota_master
MERGE INTO prima_nota_master
	USING tmp_prima_nota_master ON
		1 = 0 -- inserisce sempre. sempre NOT MATCHED
	WHEN NOT MATCHED THEN
		INSERT (pn_registrazione_numero ,pn_registrazione_data, pn_cau_cod, pn_cnt_id_cliente_fornitore, pn_tipcnt_id, pn_tipdoc_id, pn_documento_numero, pn_documento_serie, pn_documento_data, pn_documento_totale, pn_competenza, pn_competenza_iva, pn_tipo_registro, pn_numero_registro, pn_pag_cod)
		VALUES (pn_registrazione_numero ,pn_registrazione_data, pn_cau_cod, pn_cnt_id_cliente_fornitore, pn_tipcnt_id, pn_tipdoc_id, pn_documento_numero, pn_documento_serie, pn_documento_data, pn_documento_totale, pn_competenza, pn_competenza_iva, pn_tipo_registro, pn_numero_registro, pn_pag_cod)
	OUTPUT
		tmp_prima_nota_master.pn_id, INSERTED.pn_id INTO #prima_nota_master_linkage;


-- prima_nota_dettagli
MERGE INTO prima_nota_dettagli
	USING (
		SELECT
				pnd_numero_riga
				, pnd_cau_cod
				, pnd_cnt_id
				, pnd_tipcnt_id
				, pnd_dare
				, pnd_avere
				, pnd_flag_partite
				, pnd_pn_id
				, pnd_id
				, pnl_pn_id
			FROM tmp_prima_nota_dettagli
			INNER JOIN #prima_nota_master_linkage ON
				pnd_pn_id = pnl_tpn_id
		) AS query ON
		1 = 0 -- inserisce sempre. sempre NOT MATCHED
	WHEN NOT MATCHED THEN
		INSERT
			(
				pnd_numero_riga
				, pnd_cau_cod
				, pnd_cnt_id
				, pnd_tipcnt_id
				, pnd_dare
				, pnd_avere
				, pnd_flag_partite
				, pnd_pn_id
			)
		VALUES
			(
				pnd_numero_riga
				, pnd_cau_cod
				, pnd_cnt_id
				, pnd_tipcnt_id
				, pnd_dare
				, pnd_avere
				, pnd_flag_partite
				, pnl_pn_id
			)
	OUTPUT
		query.pnd_id, INSERTED.pnd_id INTO #prima_nota_dettagli_linkage;


/*
INSERT INTO prima_nota_dettagli
	(
		pnd_numero_riga
		, pnd_cau_cod
		, pnd_cnt_id
		, pnd_tipcnt_id
		, pnd_dare
		, pnd_avere
		, pnd_pn_id
	)
	SELECT
			pnd_numero_riga
			, pnd_cau_cod
			, pnd_cnt_id
			, pnd_tipcnt_id
			, pnd_dare
			, pnd_avere
			, pnl_pn_id
		FROM tmp_prima_nota_dettagli
		INNER JOIN #prima_nota_master_linkage ON
			pnd_pn_id = pnl_tpn_id
		ORDER BY
			pnd_pn_id
			, pnd_numero_riga
*/

-- prima_nota_iva
INSERT INTO prima_nota_iva
	(
		pni_numero_riga
		, pni_imponibile
		, pni_aliquota
		, pni_importo_iva
		, pni_cnt_id_iva
		, pni_tipcnt_id_iva
		, pni_cnt_id_contropartita
		, pni_tipcnt_id_contropartita
		, pni_iva_cod
		, pni_percentuale_indetraibilita
		, pni_tipo_registro
		, pni_numero_registro
		, pni_pn_id
	)
	SELECT
			pni_numero_riga
			, pni_imponibile
			, pni_aliquota
			, pni_importo_iva
			, pni_cnt_id_iva
			, pni_tipcnt_id_iva
			, pni_cnt_id_contropartita
			, pni_tipcnt_id_contropartita
			, pni_iva_cod
			, pni_percentuale_indetraibilita
			, pni_tipo_registro
			, pni_numero_registro
			, pnl_pn_id
		FROM tmp_prima_nota_iva
		INNER JOIN #prima_nota_master_linkage ON
			pni_pn_id = pnl_tpn_id
		ORDER BY
			pni_pn_id
			, pni_numero_riga

-- partite
INSERT INTO partite
		(
			pt_numero
			, pt_data_scadenza
			, pt_cnt_id
			, pt_tipo_conto
			, pt_conto
			, pt_conto_nome
			, pt_segno
			, pt_importo
			, pt_flag_crea_salda
			, pt_totale_abbuono
			, pt_doc_tipo_doc_fisc
			, pt_doc_numero
			, pt_doc_alt
			, pt_doc_data
			, pt_doc_totale
			, ban_cod_appoggio
			, bancar_id
			, tpag_id
			, pt_pn_id
			, pt_pnd_id
		)
	SELECT
			pt_numero
			, pt_data_scadenza
			, pt_cnt_id
			, pt_tipo_conto
			, pt_conto
			, pt_conto_nome
			, pt_segno
			, pt_importo
			, pt_flag_crea_salda
			, pt_totale_abbuono
			, pt_doc_tipo_doc_fisc
			, pt_doc_numero
			, pt_doc_alt
			, pt_doc_data
			, pt_doc_totale
			, ban_cod_appoggio
			, bancar_id
			, tpag_id
			, pnl_pn_id
			, pndl_pnd_id
		FROM tmp_partite
		INNER JOIN #prima_nota_master_linkage ON
			pt_pn_id = pnl_tpn_id
		INNER JOIN #prima_nota_dettagli_linkage ON
			pt_pnd_id = pndl_tpnd_id

-- imposta i documenti come contabilizzati
UPDATE documenti
	SET
		doc_contabil = 1
	FROM documenti
	INNER JOIN tmp_prima_nota_master ON
		documenti.doc_cod = tmp_prima_nota_master.pn_doc_cod

-- report
SET @result_scartati = 0

-- cancellazione tabelle temporanee
IF @lock_pratiche = 1
BEGIN
	SELECT @result_scartati = COUNT(0) FROM #documenti_scartati
	DROP TABLE #pratiche_bloccate
	DROP TABLE #documenti_scartati
END
DROP TABLE #tipo_documento_da_contabilizzare
--DROP TABLE tmp_prima_nota_master
--DROP TABLE tmp_prima_nota_dettagli
--DROP TABLE tmp_prima_nota_iva
DROP TABLE #prima_nota_master_linkage
DROP TABLE #prima_nota_dettagli_linkage
--DROP TABLE tmp_partite

	COMMIT TRANSACTION
END TRY
BEGIN CATCH
	-- N.B. Gli errori con una gravità minore o uguale a 10 sono considerati 
	--      avvisi o messaggi informativi e non vengono gestiti dai blocchi TRY...CATCH. 
	SET @bError = 1
	-- N.B. ERROR_MESSAGE(), ERROR_LINE() ecc. sono utilizzabili solo nel blocco CATCH. 
	SELECT @ErrorMessage = ERROR_MESSAGE(),
			@ErrorLine = ERROR_LINE(),
			@ErrorSeverity = ERROR_SEVERITY(),
			@ErrorState = ERROR_STATE();
	SET @ErrorMessage = @ErrorMessage + N' Linea: ' + CONVERT(NVARCHAR(10), @ErrorLine)
	IF	XACT_STATE() = -1 -- Se Transazione bloccata e uncommittable
	BEGIN
		ROLLBACK TRANSACTION
	END	
	IF	XACT_STATE() = 1 -- Transazione committable
	BEGIN
		COMMIT TRANSACTION
	END	
	-- Se XACT_STATE() = 0 significa che non c'è nessuna transazione e una COMMIT
	-- o una ROLLBACK fallirebbero
END CATCH

-- Resetta lo stato al valore di default.
SET XACT_ABORT OFF

IF	@bError = 1
BEGIN
	-- N.B. RAISERROR può generare errori con contesto compreso esclusivamente 
	--      tra 1 e 127. Il Motore di database può generare errori con contesto 0.
	--      Quindi controlliamo.
	IF	@ErrorState < 1
	OR  @ErrorState > 127
	BEGIN
		SET @ErrorState = 1
	END
	--RAISERROR('Trovati errori', 11, 1)
	-- Ritorniamo al chiamante le informazioni originali relative all'errore che ha causato
	-- l'esecuzione del CATCH block.
	RAISERROR (@ErrorMessage, -- Message text.
				@ErrorSeverity, -- Severity.
				@ErrorState -- State.
				)
END

-- fine
fine:


SELECT @result = COUNT(*) FROM tmp_prima_nota_master


END

GO
