Sprawdź status VAT i VIES

Gotowe szablony, skrypty, makropolecenia i rozszerzenia. Tutaj możesz pochwalić i podzielić się swoją twórczością z innymi użytkownikami
Parda
Posty: 3
Rejestracja: śr sty 08, 2020 3:09 am

Sprawdź status VAT i VIES

Post autor: Parda »

Witam,

Jestem osobą nową na forum ale chciałem zainteresować potencjalnych odbiorców ciekawej usługi dostępnej dla podatnik a działającej w plikach xml.

Sprawdź status VAT
"Zasady wymiany informacji pomiędzy usługą sieciową Sprawdź status VAT udostępnioną przez Ministerstwo Finansów, a oprogramowaniem interfejsowym systemów klienckich, pobierających informacje dotyczące statusu podatników jako płatników podatku VAT."

Podobne zasady informacji dotyczą usługi Sprawdź status VAT.

Niestety dostępny język kodu to makra w formacie VBA. Pytanie brzmi czy jest ktoś w stanie przepisać poniższy kod makra do OpenOffice?

1) VAT:

---------------------------------------------------------------------

Function Status_Platnika(NIP As String) As String
Dim objXml As Object
Dim Soap As String
Dim Kod As String

On Error GoTo Status_Platnika_Error

Set objXml = CreateObject("MSXML2.XMLHTTP")

Soap = "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:ns='http://www.mf.gov.pl/uslugiBiznesowe/us ... 2018/03/01'>"
Soap = Soap & "<soapenv:Header/>"
Soap = Soap & "<soapenv:Body>"
Soap = Soap & "<ns:NIP>" & NIP & "</ns:NIP>"
Soap = Soap & "</soapenv:Body>"
Soap = Soap & "</soapenv:Envelope>"

With objXml
.Open "POST", "https://sprawdz-status-vat.mf.gov.pl/", False
.setRequestHeader "Accept-Language", "PL"
.setRequestHeader "soapAction", "http://www.mf.gov.pl/uslugiBiznesowe/us ... SprawdzNIP"
.setRequestHeader "Content-Type", "text/xml; charset=utf-8"
.send (Soap)

While .readyState <> 4
DoEvents
Wend
Kod = VBA.Left(.responsexml.Text, 1)
End With

Select Case Kod
Case "N": Status_Platnika = "NIP nie jest zarejestrowany jako podatnik VAT"
Case "C": Status_Platnika = "NIP jest zarejestrowany jako podatnik VAT"
Case "Z": Status_Platnika = "NIP jest zarejestrowany jako podatnik VAT zwolniony"
Case "I": Status_Platnika = "NIP nieprawidłowy"
Case "D": Status_Platnika = "Błąd zapytania"
Case "X": Status_Platnika = "Usługa nieaktywna"
Case Else: Status_Platnika = "Nieokreślony błąd"
End Select

Set objXml = Nothing

On Error GoTo 0
Exit Function

Status_Platnika_Error:

MsgBox "Error " & Err.Number & " (" & Err.Description & ")"

End Function

---------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------


2) VIES:

---------------------------------------------------------------------

Function Check_VIES(Kraj As String, Nip As String) As Boolean
Dim objXml As Object
Dim Soap As String

Set objXml = CreateObject("MSXML2.XMLHTTP")

Soap = "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:urn='urn:ec.europa.eu:taxud:vies:services:checkVat:types'>"
Soap = Soap & "<soapenv:Header/>"
Soap = Soap & "<soapenv:Body>"
Soap = Soap & "<urn:checkVat>"
Soap = Soap & " <urn:countryCode>" & Kraj & "</urn:countryCode>"
Soap = Soap & " <urn:vatNumber>" & Nip & "</urn:vatNumber>"
Soap = Soap & " </urn:checkVat>"
Soap = Soap & "</soapenv:Body>"
Soap = Soap & "</soapenv:Envelope>"

With objXml
.Open "POST", "http://ec.europa.eu/taxation_customs/vi ... VatService", False
.send (Soap)
While .readyState <> 4: DoEvents: Wend
Check_VIES = Split(Split(.responseText, "<valid>")(1), "</valid>")(0)
End With

Set objXml = Nothing

End Function
Ostatnio zmieniony pn sty 13, 2020 3:44 pm przez Jan_J, łącznie zmieniany 1 raz.
Powód: Wątek przeniesiony z działu `Calc` do działu `Projekty użytkowników`
OpenOfficePL Standard 2012
Jan_J
Posty: 4558
Rejestracja: pt maja 22, 2009 1:20 pm
Lokalizacja: Wrocław

Re: Sprawdź status VAT i VIES

Post autor: Jan_J »

Cytowane rozwiązanie w VBA korzysta z bibioteli MSXML, więc siłą rzeczy ograniczone jest do Windows. StarBasic nie posiada w swoich zasobach analogicznej biblioteki do obsługi protokołu http(s). Ale zrobienie równoważnego skryptu w Pythonie z użyciem np. modułu requests powinno być równie proste.
Opakowanie kodu Pythona, tak by dało się go używać jako funkcji w makrach Basic Open|LibreOffice'a, wymaga trochę więcej zachodu, nie napiszę tego od ręki.
JJ
LO (7.6|24.2) ∙ Python (3.12|3.10) ∙ Unicode 15 ∙ LᴬTEX 2ε ∙ XML ∙ Unix tools ∙ Linux (Rocky|CentOS)
Parda
Posty: 3
Rejestracja: śr sty 08, 2020 3:09 am

Re: Sprawdź status VAT i VIES

Post autor: Parda »

Witam,

Jeżeli masz chęć i czas to było by fajnie wykorzystać te narzędzie do pracy wielu księgowych :)

Mnie osobiście denerwuje tylko fakt że to kolejne fajne rozwiązanie przygotowane przez ministerstwo ale działające tylko czy to na platformie W...s czy na pakiecie MS...e trochę to podpada "monopolem".

Pozdrawiam
OpenOfficePL Standard 2012
Jan_J
Posty: 4558
Rejestracja: pt maja 22, 2009 1:20 pm
Lokalizacja: Wrocław

Re: Sprawdź status VAT i VIES

Post autor: Jan_J »

Te argumenty są słuszne jak najbardziej, tylko że mało kto jest dziś na nie wyczulony. A już na pewno nie administracja państwowa, co niezmiennie mnie dziwi.

Miałem wolną godzinę, napisałem dwie funkcje w module i sprawdziłem, że działają.

Co jest do zrobienia:
1. zastanowić się, co ma być wynikiem działania tych funkcji. Obecnie przekazują kod statusu i odczytane z odpowiedzi teksty. Co tam powinno być, to zależy od przewidywanego sposobu użycia funkcji;
2. zastanowić się nad postępowaniem w przypadku niepowodzenia;
3. zastąpić wyrażenia regularne prawdziwym parsowaniem XML. Ważne dla bezpieczeństwa i pewności działania;
3. zastanowić się nad formą użytkowania, obecnie są to surowe funkcja biblioteczne;
4. jeżeli ma nastąpić integracja z (Open|Libre)Office (nie wiem czy potrzebna, a jeśli tak, to na jakim poziomie), to konieczny będzie instalator w postaci dodatku oxt i sprawdzenie wyposażenia instalacji Pythona w niezbędne moduły (requests i ew. lxml);
5. dopisać dokumentację.

Zapraszam chętnych do współpracy nad wykończeniem. W miarę wolnego czasu może spróbuję to popchnąć, ale nie obiecuję.

Dokumentacja usług w Ministerstwie Finansów: https://www.podatki.gov.pl/e-deklaracje ... ntacja-it/
Dokumentacja modułów Pythona:
* requests: https://requests.readthedocs.io/en/master/ oraz https://2.python-requests.org//pl/latest/
* re: https://docs.python.org/3/library/re.html
* xml: https://docs.python.org/3/library/xml.html
* lxml: https://lxml.de
* pakietowanie dodatków oxt: m.in. https://forum.openoffice.org/en/forum/v ... 02#p477902 oraz https://forum.openoffice.org/en/forum/v ... 47&t=99266
* dostęp z poziomu funkcji StarBasic w OpenOffice do funkcji pisanych w innych językach: https://ask.libreoffice.org/en/question ... sic-macro/ oraz https://stackoverflow.com/questions/759 ... e-org-calc (są to kopie z dawnych opisów na starym forum oooforum.org, dziś już nieczynnym)

Kod wstawiam poniżej

Kod: Zaznacz cały

#!/usr/bin/env python3

import requests
import re

'''
Szkicowa implementacja funkcji status_platnika i check_vies
na podstawie kodu VBA dostarczonego w wątku dyskusyjnym
https://forum.openoffice.org/pl/forum/viewtopic.php?f=28&t=5201
Kod powstał w ramach dyskusji uczestników forum użytkowników OpenOffice i LibreOffice.

Funkcje sprawdzają status i dane płatnika podatku VAT w serwisach Ministerstwa Finansów oraz ec.europa.eu.

Kod jest udostępniany na licencji Public Domain, bez żadnej gwarancji działania.
Usuwanie niniejszej notki z treści modułu nie jest dozwolone;
w przypadku modyfikacji należy ją uzupełnić o dokumentację autorstwa modyfikacji.

Wersja 0.03 by @Jan_J at https://forum.openoffice.org/pl, Wrocław, 14 stycznia 2020
'''

def take_content(element, xmltext):
    '''
    z argumentu xmltext (w założeniu jest to tekstowa reprezentacja dokumentu XML)
    pobiera zawartość elementu o wskazanej nazwie
    w przypadku niepowodzenia przekazuje wynik None
    problemy:
    * pobiera tylko pierwsze wystąpienie
    * pobiera tylko zawartość czysto tekstową
    * używa regex zamiast parsera xml
    * nie jest odporny na nielegalne nazwy elementu
    '''
    expr = '<{ELEMENT}>([^<]*)</{ELEMENT}>'.format(ELEMENT = element)
    try:
        return re.search(expr, xmltext).groups()[0]
    except (AttributeError, IndexError):
        return None

# adresy usług
URL_CHECK_NIP = "https://sprawdz-status-vat.mf.gov.pl/"
URL_MF_USLUGI_BIZNESOWE = "http://www.mf.gov.pl/uslugiBiznesowe/uslugiDomenowe/AP/WeryfikacjaVAT/2018/03/01"
URL_MF_AKCJA_SPRAWDZ_NIP = URL_MF_USLUGI_BIZNESOWE  + "/WeryfikacjaVAT/SprawdzNIP"
URL_CHECK_VIES = "http://ec.europa.eu/taxation_customs/vies/services/checkVatService"

# szkielet zapytania o NIP
nip_envelope = """
<soapenv:Envelope 
        xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' 
        xmlns:ns='""" + URL_MF_USLUGI_BIZNESOWE  + """'>
    <soapenv:Header/>
    <soapenv:Body><ns:NIP>{NIP}</ns:NIP></soapenv:Body>
</soapenv:Envelope>
"""

# szkielet zapytania o płatnika VAT
vat_envelope = """
<soapenv:Envelope 
        xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' 
        xmlns:urn='urn:ec.europa.eu:taxud:vies:services:checkVat:types'>
    <soapenv:Header/>
    <soapenv:Body>
        <urn:checkVat>
            <urn:countryCode>{COUNTRY}</urn:countryCode>
            <urn:vatNumber>{NIP}</urn:vatNumber>
        </urn:checkVat>
    </soapenv:Body>
</soapenv:Envelope>
"""

HEADERS_CHECK_NIP = {
    "Accept-Language": "PL",
    "soapAction": URL_MF_AKCJA_SPRAWDZ_NIP,
    "Content-Type": "text/xml; charset=utf-8",
}

HTTP_OK = 200

def status_platnika(nip, service = URL_CHECK_NIP, headers = HEADERS_CHECK_NIP):
    '''
    odpytuje serwis MF o status płatnika VAT
    argumenty:
    * nip: ciąg cyfr (tekst) z numerem NIP, bez przerw i kresek
    * service: adres URL usługi (z wartością domyślną)
    * headers: słownik pól nagłówkowych zapytania (z wartością domyślną)
    wynik w formacie
    * status HTTP,
    * kod statusu odpowiedzi wg dokumentacji serwisu wyłuskana z elementu Kod
    * odpowiedź wyłuskana z elementu Komunikat
    '''
    data = nip_envelope.format(NIP = nip)
    response = requests.post(service, headers = headers, data = data)
    kod = response.status_code
    if kod == HTTP_OK:
        tekst = response.text
        status = take_content('Kod', tekst)
        komunikat = take_content('Komunikat', tekst)
    else:
        status = '?'
        komunikat = '?'
    return kod, status, komunikat

def check_vies(country, nip, service = URL_CHECK_VIES, headers = { }):
    '''
    odpytuje serwis ec.europa.eu o dane adresowe płatnika VAT
    argumenty:
    * country: tekstowy kod państwa akceptowany przez serwis (dla Polski: "PL")
    * nip: ciąg cyfr (tekst) z numerem NIP, bez przerw i kresek
    * service: adres URL usługi (z wartością domyślną)
    * headers: słownik pól nagłówkowych zapytania (domyślnie pusty)
    wynik w formacie
    * status HTTP,
    * kod poprawności odpowiedzi wg dokumentacji serwisu wyłuskany z elementu valid albo faultstring
    * nazwa płatnika wyłuskana z elementu name
    * adres płatnika wyłuskany z elementu address
    '''
    data = vat_envelope.format(COUNTRY = country, NIP = nip)
    response = requests.post(service, headers = headers, data = data)
    kod = response.status_code
    if kod == HTTP_OK:
        tekst = response.text
        status = take_content('valid', tekst)
        if status is not None:
            name = take_content('name', tekst)
            address = take_content('address', tekst)
        else:
            status = take_content('faultstring', tekst)
            name = '?'
            address = '?'
    else:
        status = '?'
        name = '?'
        address = '?'
    return kod, status, name, address

if __name__ == '__main__':

    print('=== testy')
    # 896-000-54-08 Uniwersytet Wrocławski
    # 896-000-54-18 nic
    # 896-000-58-51 Politechnika Wrocławska
    # 123-456-78-90 bzdura ze zgodną liczbą cyfr
    # 123-456-78-9 bzdura z niezgodną liczbą cyfr
    nipy_do_sprawdzenia = ('8960005408', '8960005418', '8960005851', '1234567890', '123456789')
    kraje_do_sprawdzenia = ('PL', 'PX')

    for nip_spr in nipy_do_sprawdzenia:
        print('sprawdź nip:',  nip_spr)
        y = status_platnika(nip_spr)
        print(y)
        print('---')

        for kraj in kraje_do_sprawdzenia:
            print('sprawdź vies:', kraj, nip_spr)
            y = check_vies(kraj, nip_spr)
            print(y)
            print('---')

    print('=== ok')

JJ
LO (7.6|24.2) ∙ Python (3.12|3.10) ∙ Unicode 15 ∙ LᴬTEX 2ε ∙ XML ∙ Unix tools ∙ Linux (Rocky|CentOS)
Parda
Posty: 3
Rejestracja: śr sty 08, 2020 3:09 am

Re: Sprawdź status VAT i VIES

Post autor: Parda »

Niestety chyba temat umarł śmiercią naturalną z powodu braku czasu i zainteresowania ;)
OpenOfficePL Standard 2012
Jan_J
Posty: 4558
Rejestracja: pt maja 22, 2009 1:20 pm
Lokalizacja: Wrocław

Re: Sprawdź status VAT i VIES

Post autor: Jan_J »

Ja teraz mam sesję, ale nawet nie o to chodzi.

Po prostu nie bardzo wiem, jaki byłby satysfakcjonujący dla ew. beneficjentów sposób użytkowania tej funkcji. Sam nie jestem księgowym, nie wymyślę.

Np. makropolecenie dla Calca sprawdzające nip z bieżącej/zaznaczonej komórki/zakresu? łatwe.
Funkcja do użycia w formule: argument = nip; wynik = opis? kłopotliwe ze względu na jakość interfejsu Python--Basic.
Okno dialogowe typu kreator? oczywiste (z wyjątkiem ergonomii projektu), ale ja tego bardzo nie lubię robić. Dlatego umieściłem w zapisie licencję zachęcającą do rozbudowy.
Inna forma?
JJ
LO (7.6|24.2) ∙ Python (3.12|3.10) ∙ Unicode 15 ∙ LᴬTEX 2ε ∙ XML ∙ Unix tools ∙ Linux (Rocky|CentOS)
ODPOWIEDZ