toudi/ksef

[ wysyłka ] - nie wysyłanie już wysłanych faktur

Closed this issue · 18 comments

opcja podobna do opcji -refresh przy komendzie download. chodzi o to, żeby program nie wysyłał wszystkich faktur z katalogu źródłowego a jedynie te których jeszcze nie wysłał. Jest to opcja przydatna wtedy, kiedy w kilku plikach wejściowych pojawi się błąd ale pozostałe wyślą się bez błędu. wtedy chcielibyśmy ponowić wysyłkę i wówczas nie możemy wysyłać ponownie wszystkich faktur bo stworzą się duplikaty.

Nie wiem jak zachowa się środowisko produkcyjne w takim przypadku, ale i tak by trzeba to jakoś obsłużyć.
Unikamy też przypadku gdy faktury w katalogu do wysyłki pojawią się "hurtowo" i coś może się pojawić
w trakcie trwającej wysyłki.

ja pisałem do ministerstwa w tej sprawie ale niestety nic mi nie odpisali - pytałem ich czy zamiast tworzenia duplikatu KSeF mógłby:

a/ zrobić no-op - czyli po prostu zignorować duplikat
b/ wyrzucić błąd - coś na zasadzie "hej - przesłałeś duplikat"

tak na marginesie zastawnawiam się czy (i w jaki sposób) poinformować KSeF o tym, że faktura została zapłacona. chodzi o to, że jeśli ja jako wystawca wrzucę fakturę do KSeF to muszę od niej zapłacić podatek, adresat faktury może ją wrzucić w koszty pomimo że za nią jeszcze nie zapłacił - czyli ja jestem defacto w plecy o podatek. (Tak tak oczywiście mam świadomość faktur pro forma ale nie każdy może z nich korzystać). No i załóżmy że trafiam na uczciwego kontrahenta który mi zapłaci. czy jestem wówczas zobowiązany powiadomić KSeF że faktura jest opłacona?

Nic nie odpisali, bo sami nic nie wiedzą, taka prawda.
Jak czytam na forum: https://4programmers.net/Forum/Nietuzinkowe_tematy/355933-krajowy_system_e_faktur
to jeśli już coś odwiedzą to nie jest to nic konkretnego.

Mam jakiś problem, nowa wersja daje taki komunikat:

ksef upload -i -p KSeF/out -token 45F43091CC43033DAA6D3C32B37D0FDBE6E95E52C6A23E1C62D2DBD701D15DA2 -t -f
błąd wykonania -i:
cannot open registry: Unexpected error during opening registry file: registry file does not exist

Zarówno jak jest przełacznik: "-f", jak i przy jego braku.
Gorzej że jak chciałem sprawdzić starą wersję to jest tak:

ksef.old upload -i -p KSeF/out -token 45F43091CC43033DAA6D3C32B37D0FDBE6E95E52C6A23E1C62D2DBD701D15DA2 -t
request URL: https://ksef-test.mf.gov.pl/api/online/Session/AuthorisationChallenge
error running upload:
cannot login to gateway: unexpected response code: 400 != 2xx or err: <nil>

Bramka działa, bo przez web można się dostać. Spróbuję jeszcze z tymi nowymi poziomami logowania.
[Edit]
Zapomniałem że logowanie można zmienić tylko w nowej wersji, a ta nawet nie próbuje wysyłać bez pliku rejestru.

aaa.. wszystko jasne. mam idiotyczny warunek w kodzie, zaraz to poprawię:

	registry, err := LoadRegistry(fileName)
	if registry == nil && err == ErrDoesNotExist {
		registry = NewRegistry()
	}

	if err != nil {
		return nil, fmt.Errorf("Unexpected error during opening registry file: %v", err)
	}

🤦

0.1.20-rc4

Na tej wersji jest tak:

ksef -v -log - upload -i -p KSeF/out -token AC1A6E417C7E7F7C1C4805D7D1BCACAEF7503B40106D842905E756B5624D9590 -t
time=2023-12-27T14:04:04.630+01:00 level=INFO msg="start programu"
time=2023-12-27T14:04:04.631+01:00 level=DEBUG msg=HTTPSession::Request method=POST URL=https://ksef-test.mf.gov.pl/api/online/Session/AuthorisationChallenge
time=2023-12-27T14:04:04.745+01:00 level=DEBUG msg="HTTPSession::JSONRequest response" content="{\"timestamp\":\"2023-12-27T13:04:04.744Z\",\"challenge\":\"20231227-CR-5F84EE3DA6-7931497C9B-13\"}" "status code"=201
time=2023-12-27T14:04:04.745+01:00 level=DEBUG msg=InteractiveSession::Login challengePlaintext=AC1A6E417C7E7F7C1C4805D7D1BCACAEF7503B40106D842905E756B5624D9590|1703682244744
time=2023-12-27T14:04:04.746+01:00 level=DEBUG msg="HTTPSEssion::XMLRequest rendered XML" content="<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<auth:InitSessionTokenRequest\n    xmlns=\"http://ksef.mf.gov.pl/schema/gtw/svc/online/types/2021/10/01/0001\"\n    xmlns:types=\"http://ksef.mf.gov.pl/schema/gtw/svc/types/2021/10/01/0001\"\n    xmlns:auth=\"http://ksef.mf.gov.pl/schema/gtw/svc/online/auth/request/2021/10/01/0001\">\n    <auth:Context>\n        <Challenge>20231227-CR-5F84EE3DA6-7931497C9B-13</Challenge>\n        <Identifier xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n            xsi:type=\"types:SubjectIdentifierByCompanyType\">\n            <types:Identifier>9999999990</types:Identifier>\n        </Identifier>\n        <DocumentType>\n            <types:Service>KSeF</types:Service>\n            <types:FormCode>\n                <types:SystemCode>FA (2)</types:SystemCode>\n                <types:SchemaVersion>1-0E</types:SchemaVersion>\n                <types:TargetNamespace>http://crd.gov.pl/wzor/2023/06/29/12648/</types:TargetNamespace>\n                <types:Value>FA</types:Value>\n            </types:FormCode>\n        </DocumentType>\n        <Encryption>\n            <types:EncryptionKey>\n                <types:Encoding>Base64</types:Encoding>\n                <types:Algorithm>AES</types:Algorithm>\n                <types:Size>256</types:Size>\n                <types:Value>YsOeDY2aW5kAM8s3/HrCRtavD4xGiN7E1zYIvNQH0W1bEdOpI7vAIugmzRw62IXw4dalB1Qhe8qlbJMKJ4Cp0/j5J5I0ArXvYNfhq4weltDs18Or9S9fitwcEHlgDeOQYya0anG0vi4vZHUBL+14TNg25DchEdvhVtMsMnQi5SQng4gPzfI6/HcRu0m62PISXcrLeAwVOe969pZI7IJxGdr1ejE8Q+eNDw160O4b0CnZ0c0AN7fHGRLDuRFVd7e0aMHnOFFlzblX07RmKQJdzfHLNAqLlDb8yq0dEFdrea2T2+iOoVeOjK51ngMQ1ffYfnioN8ttCb6SzWG3alaQrw==</types:Value>\n            </types:EncryptionKey>\n            <types:EncryptionInitializationVector>\n                <types:Encoding>Base64</types:Encoding>\n                <types:Bytes>16</types:Bytes>\n                <types:Value>FnpJk1SmTpilkDpoxB7FiQ==</types:Value>\n            </types:EncryptionInitializationVector>\n            <types:EncryptionAlgorithmKey>\n                <types:Algorithm>RSA</types:Algorithm>\n                <types:Mode>ECB</types:Mode>\n                <types:Padding>PKCS#1</types:Padding>\n            </types:EncryptionAlgorithmKey>\n            <types:EncryptionAlgorithmData>\n                <types:Algorithm>AES</types:Algorithm>\n                <types:Mode>CBC</types:Mode>\n                <types:Padding>PKCS#7</types:Padding>\n            </types:EncryptionAlgorithmData>\n        </Encryption>\n        <Token>BLxUGral/jJUKKlmo5rtsGxRuCTvXyFoqaixKYpiBtj5xRGPzM7Ef6ZKzCCxpAM4htZzVWDYoiCRr8Rghv1O0icorHmFtpuUFDyCsZroppvJSKEsryQ2+VVhlEZM/LiUqaFVKmd3MXDsOLhEwzE3h4XQeOuILio34TLVeGehNutX0oHDssnrkE3mEVwyK/r03PiqqMnvKJ0AusNddw4nBHytg5QTLlrIRQe46l5wYL4ngwrDkZIs62gHIDJOWVDA6UOi9L14+mh+tZ7Uv63GPRferJJdhpGv92j584QfcEbIHOzXK9RLGTXxD4BnMC13J9x7A3J3pVQmXN5b9xdXrw==</Token>\n    </auth:Context>\n</auth:InitSessionTokenRequest>"
time=2023-12-27T14:04:04.746+01:00 level=DEBUG msg=HTTPSession::Request method=POST URL=https://ksef-test.mf.gov.pl/api/online/Session/InitToken
time=2023-12-27T14:04:04.829+01:00 level=DEBUG msg="HTTPSession::XMLRequest response" content="{\"exception\":{\"serviceCtx\":\"default\",\"serviceCode\":\"20231227-EX-77D452A7A1-06B9D1614D-1C\",\"serviceName\":\"online.session.session.token.init\",\"timestamp\":\"2023-12-27T13:04:04.835Z\",\"referenceNumber\":\"20231227-SE-D829D2514D-4C166F2DC8-03\",\"exceptionDetailList\":[{\"exceptionCode\":21301,\"exceptionDescription\":\"Brak autoryzacji.\"}]}}" "status code"=400
błąd wykonania -i:
cannot login to gateway: unexpected response code: 400 != 2xx or err: <nil>
time=2023-12-27T14:04:04.829+01:00 level=INFO msg="koniec programu"

Sprawdzałem na "starym" i teraz wygenerowanym tokenie dla nip: 9999999999
Coś "oni" zmienili, czy jak, bo nawet ta starsza wersja 0.1.19 daje teraz taki sam komunikat i nie wysyła.

a czy jest możliwość że ktoś Ci albo usunął token albo zmienił na nim uprawnienia i że nie możesz wysyłać faktur ? przed chwilą próbowałem na swoim numerze NIP i przeszło bez problemu ale później spróbuję wygenerować dla sztucznego NIP'u token.

Dzięki za naprowadzenie, to już trzeci raz. Ja sam tych faktur do wysyłki nie robię i ten co robi zawsze mi jakiś psikus
z nipem robi, byłem przekonany że to 9999999999, a było 9999999990 !Nic to, program działa, tyle że mam tak:

ksef upload -t -i -p KSeF/out -token 2356E5A8DF63195FE4D95AB583F8D2D95D05959D996E7BF3E67E9483D9FB294B
ksef status -p KSeF/out/registry.yaml -o KSeF/UPO/231227 -m -xml

Wszystko OK, dogrywam do katalogu "KSeF/out" trzy kolejne faktury i mam:

ksef upload -t -i -p KSeF/out -token 2356E5A8DF63195FE4D95AB583F8D2D95D05959D996E7BF3E67E9483D9FB294B
Wygląda na to, że poprzednio użyta została komenda 'upload' na tym rejestrze.
Jeśli na pewno chcesz ponowić wysyłkę, uzyj flagi '-f'

Tak to ma być?

Ok, po pierwsze - myślę, że dodam sprawdzanie poprawności NIPu (póki co tylko długość bo przecież żaden z tych sztucznych NIPów i tak nie przejdzie walidacji (tam jest bodaj jakieś śmieszne modulo 10 czy coś)

Po drugie - tak, po raz kolejny muszę użyć argumentu "this is not a bug, this is a feature" :D

bug vs feature

Idea całej tej komendy (i sprawdzania) była taka że masz paczkę powiedzmy 10 faktur, wrzucasz je do katalogu i teraz tak:

1/ wydajesz komendę "upload"
2/ wydajesz komendę "status" - powiedzmy że przechodzi 8 faktur, dwie masz do poprawki
3/ poprawiasz faktury, ponownie "upload" (z flagą -f) i ponownie status i tak do skutku

Nawet jeśli użyjesz opcji -f to faktury które już mają nadane numery KSeF się nie wyślą.. no przynajmniej nie powinny, chyba że znów zrobiłem jakąś kardynalną pomyłkę podczas nocnej sesji kodowania. Ale warunkiem koniecznym jest najpierw wydanie komendy status tak żeby pobrać numery referencyjne KSeF - inaczej program nie będzie miał jak sprawdzić czy wysłałeś faktury czy nie

Inaczej mówiąc - nie przewidziałem, że będziesz chciał mieć jeden katalog do wysyłki do którego będziesz non stop dorzucał kolejne faktury. Podejrzewam, że wtedy parsowanie yaml'a z rejestrem mogłoby zająć sporo czasu. Myślałem, że po poprawnym wysłaniu faktur skasujesz plik rejestru, UPO, etc i zaczniesz zabawę od nowa. Jestem jednak otwarty na propozycje - grunt, żeby one gwarantowały jako-taką kompatybilność wstecz :)

W trybie demona który planuję doimplementować w ogóle będzie to tak zrobione że każdy plik będzie miał osobny rejestr który po poprawnym przetworzeniu będzie usuwany

Jeśli jeszcze nie jest to klarowne (a po długości mojego komentarza wnoszę że chyba nie :D) to daj znać czy masz jakieś pytania i postaram się to wyjaśnić lepiej

Dzięki, teraz wszystko jasne. Jutro sprawdzę dokładnie, ale już teraz wydaje się działać tak jak napisałeś.
Ta opcja -f sprawdza się nawet jak się dorzuca nowe faktury do katalogu.

tak, zgadza się. tylko tak jak napisałem - weź pod uwagę że rejestr to zwykły plik yaml. z dużym przymrużeniem oka możnaby powiedzieć, że jest to baza NoSQL w pojedynczym pliku ale zdecydowanie ma swoje limity. Jeśli będziesz w nieskończoność dorzucał faktury to pewnie przepełnisz pamięć :)

Myślę, że jeszcze kompromisem mogłoby być to, że jeśli program zauważy, że wszystkie pliki z katalogu zostały zapisane w rejestrze i mają nadany numer KSeF to wtedy usunie z rejestru ID sesji (bo to właśnie niepuste ID sesji powoduje wyświetlenie komunikatu który widzisz). wtedy po pomyślnym zsynchronizowaniu faktur i dograniu nowych nie zobaczysz już ostrzeżenia

Jasne, zaplanowane mam usuwanie/przeniesienie plików po poprawnej wysyłce.
Ta opcja będzie przydatna właśnie gdy coś pójdzie nie tak, np. padnie internet, itd.

właśnie myślałem o tym, czy dodać flagę czyszczenia katalogu do komendy status. Tyle tylko, że to musi ładnie współgrać z lokalnym generowaniem PDF (zaimplementowałem już taką opcję do programu - zobacz na stronie dokumentacji). Chodzi o to, że żeby wygenerować lokalnie PDF musisz mieć też źródłówkę XML. Czyli mógłbym zrobić tak że:

./ksef status -o "inny/katalog/{NIP}/" -cr -m

co spowodowałoby:

  • utworzenie katalogu dynamicznie na podstawie NIP'u w fakturze tj. inny/katalog/1111111111, inny/katalog/2222222222 itd (oczywiście jak nie podasz w treści -o tego specjalnego stringu {NIP} to działałoby to tak jak do tej pory
  • przerzucenie tam UPO

no i mam małe schody.. bo żeby wygenerować lokalny PDF potrzeba źródłowego XML - spoko, mogę skopiować do katalogu wyjściowego - oraz pliku rejestru. a co jak użytkownik nie będzie chciał generować PDF ?

Ja mam własne faktury już w pdf i jeśli to nie będzie konieczne, nie będę generował zewnętrznych pdfów.
Dlatego moje wymagania w temacie pdf, są minimalne. :)

no właśnie figiel polega na tym, że własny PDF możesz mieć ale tylko i wyłącznie jeśli wrzucisz do niego kod QR i link do weryfikacji KSeF :D nie wiem czy jest to zapisane w ustawie ale takie były jakieś doniesienia - inaczej bym nie robił aż takiej kołomyi z renderowaniem bo swoje faktury też renderuję osobno :) nie wspominając o tym, że jeśli dobrze zrozumiałem to ministerstwo chce żeby jedyną formą wysyłki faktury był KSeF a nie np. email - tyle przynajmniej teoria.. :)

Cóż, ma to (KSeF) być uruchomione 1 lipca, a dalej nic nie jest pewne i ustalone.
W takim razie rób tak jak uważasz, zobaczymy co z tego wyniknie.
Ja będę testował nowe wersje i informował czy działają zgodnie z oczekiwaniem. :)