Skocz do zawartości

[Sfera] Odczytywanie błędów podczas realizacji ZK do WZ

Polecane posty

Mam kawałek kodu, który realizuje pozycje ZK do WZ. Niestety, jakbym się nie starał się go walidować, to magazynierzy zawszę są w stanie dokonać jakiś dziwnych wyborów, albo handlowcy namieszają coś w ZK, że całość mi się wysypuje na poziomie WypelnijNaPodstawieZK. Dlatego zastanawiam się, czy aby przypadkiem nie dopisać kawałka wywołania, który by tylko spróbował jakoś sprawdzić dane i tutaj moje pytania:

- czy do metody WypelnijNaPodstawieZK  mogę podpiąć WypiszBledy, tak jak do całego ZK i zadziała to podobnie, czy zdąży sypnąć błędem?

- czy jest jakaś metoda, bo w dokumentacji takiej nie widzę, która wykona "sprawdzenie", na zasadzie zapisania, ale nie utworzy dokumentu i zaśmieci systemu, ale zwróci błędy związane z tworzeniem takiego ZK?

A może ogólnie pomysł do D, i jest inny sposób? :P

 

Kod cały mój poniżej:

{
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd H:mm:ss")+" - dodawanie WZki do wybranych pozycji."); 	
// przygotowanie danych
IAsortymenty asortyment = sfera.PodajObiektTypu<IAsortymenty>();
IPodmioty podmioty = sfera.PodajObiektTypu<IPodmioty>();
IUzytkownicy uzytkownicy = sfera.PodajObiektTypu<IUzytkownicy>();
IStatusyDokumentowDaneDomyslne statusyDD = sfera.PodajObiektTypu<IStatusyDokumentow>().DaneDomyslne; 
Konfiguracja konfWz = sfera.PodajObiektTypu<IKonfiguracje>().DaneDomyslne.WydanieZewnetrzne;
string stock; stock = results.stock;
Magazyn mag = sfera.PodajObiektTypu<IMagazyny>().Dane.Wszystkie().Where(m => m.Symbol == stock).FirstOrDefault();                   
IWydaniaZewnetrzne dokumentWydania = sfera.PodajObiektTypu<IWydaniaZewnetrzne>();
IZamowieniaOdKlientow zamowienia = sfera.PodajObiektTypu<IZamowieniaOdKlientow>();
// pobranie danych jakiegokolwiek ZK, aby ustawić parametry
int docid; docid = results.docid;
var zk = zamowienia.Dane.Wszystkie().Where(p => p.Id == docid).FirstOrDefault(); // znalezienie zamówienia                  
using (IWydanieZewnetrzne wz = dokumentWydania.Utworz(konfWz))
  {
  // przeniesienie parametrów z ZK
  ParametryGrupowaniaPodstawowe parametryGrupowania = new ParametryGrupowaniaPodstawowe();
  parametryGrupowania.MetodaGrupowaniaPozycji = MetodaGrupowaniaPozycji.BezKonsolidacji;
  parametryGrupowania.MetodaWyliczeniaCen = MetodaWyliczeniaCen.PrzepisanieZDokumentuGlownego;
  parametryGrupowania.MiejsceDostawy = zk.MiejsceDostawy;
  parametryGrupowania.MiejsceDostawyTyp = MiejsceDostawyTyp.Nabywca;
  parametryGrupowania.NabywcaSprzedawca = zk.NabywcaSprzedawcaWybrany;
  IAplikatorSkutkowMagazynowych aplikatorSM = (IAplikatorSkutkowMagazynowych)wz;
  
  wz.Dane.Magazyn = mag;
  wz.Dane.StatusDokumentu = statusyDD.Rozchod_WydanyTowar;
  wz.Dane.Podtytul = zk.Podtytul;
  


  
  IDokumentZRozbiciem dok = (IDokumentZRozbiciem)wz;
  // wypełnienie pozycji na podstawie ZK
  foreach(var posadd in results.pos)
    {
    int posdocid; int posid; decimal posq; int posbatch; string comment;
    posdocid = posadd.docid; posid = posadd.id; posq = posadd.quantity; posbatch = posadd.batch; comment = posadd.comment;
    //Console.WriteLine("Pobieranie pozycji: "+posid+" z ZK "+posdocid);
    var zamowienie = zamowienia.Dane.Wszystkie().Where(p => p.Id == posdocid).FirstOrDefault(); // znalezienie zamówienia
    var poz = wz.WypelnijNaPodstawieZK(zamowienie.Pozycje.Where(p => p.Id == posid),zamowienie,parametryGrupowania).Single(); // dodanie pozycji z ZK
    //var poz = wz.WypelnijNaPodstawieDokumentuZaliczkowego(zamowienie.Pozycje.Where(p => p.Id == posid),zamowienie,parametryGrupowania).Single(); 
    Console.WriteLine("Dodanie pozycji: "+posid+", "+poz.AsortymentAktualny.Nazwa);
    poz.Opis = comment;
    poz.CenaRecznieEdytowana = true;
    if(posadd.batch!=null)
      {
      poz.Ilosc = 0; // ustawiamy na 0, wyjdzie z rozbicia
      aplikatorSM.AplikujSkutkiMagazynowe(poz); // poprawka od Insertu na poprawne działanie skutku magazynu
      var r = dok.RozpocznijRozbicie(poz) as IRozbiciePozycjiRozchodowe;
      Console.WriteLine("Wprowadzenie partii: "+posbatch+" w ilości "+posq);
      r.Pozycje.Where(p => p.PartiaZrodlowa.Id == posbatch).Single().Ilosc = posq;
      foreach(var pozr in r.Pozycje.Where(p => p.PartiaZrodlowa.Id != posbatch && p.Ilosc > 0m)) 
        {
      	pozr.Ilosc = 0m;
        }
     foreach(var pozr in r.Pozycje.Where(p => p.PartiaZrodlowa.Id != 0 )) 
       {
     	Console.WriteLine("Wybrane partie: "+pozr.PartiaZrodlowa.Id+" = "+pozr.Ilosc);
       }
      r.ZakonczRozbicie();
      aplikatorSM.AplikujSkutkiMagazynowe(poz); // ponowna poprawka na poprawne rozbicie
      }
    else
      {
      poz.Ilosc = posq; // ustawiamy na 0, wyjdzie z rozbicia
      aplikatorSM.AplikujSkutkiMagazynowe(poz);
      }
    //Console.WriteLine("Ilość na pozycji: " + poz.Ilosc);
    //wz.Przelicz();
    }
  // wypełnienie pozycji na podstawie asortymentu
  foreach(var posadd in results.posextra)
    {
    int posid; decimal posq; 
    posid = posadd.id; posq = posadd.quantity;
    Asortyment a = asortyment.Dane.Wszystkie().Where(t => t.Id == posid).First();
    var poz = wz.Pozycje.Dodaj(a,posq, a.JednostkaSprzedazy);
    Console.WriteLine("Dodanie pozycji dodatkowej: "+poz.AsortymentAktualny.Nazwa);
    // jeśli jest opis pozycji
    if(posadd.desc!=null && posadd.desc!="") {
      string posd; posd = posadd.desc;
      poz.Opis = posd; }
    // jeśli jest cena pozycji
    if(posadd.price!=null) {
      decimal posp; posp = posadd.price;
      poz.Cena.NettoPoRabacie = posp; }
    wz.Przelicz();
    }   
  
  // poprawka na nabywcę
  if(wz.Dane.NabywcaSprzedawca==null) {
    wz.Dane.NabywcaSprzedawca = wz.Dane.Podmiot;
    wz.Dane.RolaInnegoPodmiotu = (byte)RolaInnegoPodmiotu.InnyNabywca; }
  // ustawienie daty
  if(results.date!=null && results.date!="") {
    string dateString = results.date+" 07:00:00,000";
    DateTime wzDate = DateTime.ParseExact(dateString,"yyyy-MM-dd HH:mm:ss,fff",System.Globalization.CultureInfo.InvariantCulture);
    wz.Dane.DataWydaniaWystawienia = wzDate;    
    wz.Dane.DataWprowadzenia = wzDate;                      
    Console.WriteLine("Data wystawienia: " + wzDate); }
  // dopisanie transportu, jeśli jest - DO USUNIĘCIA!!!!
  decimal transport; transport = results.transport;
  if(transport!=0) {
    Asortyment a = asortyment.Dane.Wszystkie().Where(t => t.Symbol == "U Transport").First();
    var poz = wz.Pozycje.Dodaj(a, 1m, a.JednostkaSprzedazy);
    poz.Cena.NettoPoRabacie = transport; }
  // osoba wystawiająca
  string sign = results.sign;
  wz.Dane.WystawilaOsoba = uzytkownicy.Dane.Wszystkie().Where(p => p.Sygnatura == sign).FirstOrDefault().Osoba;
  wz.Dane.Uwagi = results.comment;
  // zapisywanie i eksportowanie wydruku
  if(wz.Zapisz())  
    {
    Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd H:mm:ss")+" - dodano WZkę: "+wz.Dane.NumerWewnetrzny.PelnaSygnatura);
    response = "{ \"number\":\""+wz.Dane.NumerWewnetrzny.PelnaSygnatura+"\", \"id\":\""+wz.Dane.Id+"\" }"; 
    // eksportowanie do PDF
    Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd H:mm:ss")+" - eskportowanie pliku PDF: "+wz.Dane.NumerWewnetrzny.PelnaSygnatura);
  //pobranie managera drukowania
  IWydruki manager = sfera.PodajObiektTypu<IWydruki>();
  // utworzenie zadania drukowania
  using (IWydruk wydruk = manager.Utworz(TypWzorcaWydruku.WydanieZewnetrzne))
    {
    // wskazanie obiektu do wydruku
    wydruk.ObiektDoWydruku = wz.Dane;
    using (var podmiot = sfera.PodajObiektTypu<IPodmioty>().Znajdz(wz.Dane.Podmiot))
      {
      IOperacjePodmiotuDlaDokumentu operacje = podmiot.OperacjePodmiotuDlaDokumentu[wz.Dane.Konfiguracja];
      wydruk.ParametryDrukowania.WybranyWzorzec = operacje.WzorzecWydruku;
      wydruk.ObiektDoWydruku = wz.Dane;
      string filename; filename = "wz"+wz.Dane.Id;
      //if(Globals.mode=="developer") filename = "wz"+wz.Dane.Id+"_DEV"; else filename = "wz"+wz.Dane.Id;
      wydruk.ParametryDrukowania.NazwaDokumentuUzytkownika = filename;
      wydruk.ParametryDrukowania.SciezkaEksportu = @"N:\";
      wydruk.Eksport();                      
      }
    } 
    
    }
  else { Globals.errors = ""; wz.WypiszBledy(); Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd H:mm:ss")+" - błąd przy dodawaniu WZki: "+Globals.errors );  response = "{ \"error\":\""+Globals.errors+"\" }"; }
  }                	
}

 

Link to postu

Co Pan rozumie pod pojęciem:

Cytat

podpiąć WypiszBledy, tak jak do całego ZK 

? Metodę WypiszBledy opisaną w dokumentacji można wywołać w każdej chwili i jeśli istnieją błędy ustawione na dodawanym/edytowanym obiekcie to zostaną one wypisane. Należy jednak mieć na uwadze to, że niektóre walidacje są wykonywane dopiero przy zapisie obiektu (zazwyczaj są to jakieś ciężkie walidacje, których z powodów wydajnościowych nie chcemy wykonywać w trakcie edycji) więc może wystąpić taka sytuacja, że metoda WypiszBledy nie pokaże ich, ale zapis się nie powiedzie i dopiero po nieudanym zapisie uda się te błędy odczytać.

Cytat

czy jest jakaś metoda, bo w dokumentacji takiej nie widzę, która wykona "sprawdzenie", na zasadzie zapisania, ale nie utworzy dokumentu i zaśmieci systemu, ale zwróci błędy związane z tworzeniem takiego ZK?

Taką metodą jest właśnie WypiszBledy z dokumentacji. Poza tym wywołanie Zapisz nigdy nie powinno "zaśmiecić" systemu obiektem, który jest niespójny z punktu widzenia walidacji biznesowych.

Pytanie zasadnicze brzmi - co oznacza u Pana to:

Cytat

całość mi się wysypuje na poziomie WypelnijNaPodstawieZK

Bo jak domniemam tutaj nie chodzi o błędy biznesowe tylko jakieś wyjątki, które z pewnych powodów są rzucane podczas wykonywania tej metody? Jeśli tak to tutaj ciężko jest cokolwiek doradzać bez analizy konkretnych przypadków.

Link to postu

Ponownie zaznaczę, że moje pytanie wynika trochę z leniwości, bo nie chce mi się szukać i dorabiać walidacji na każdy problem, i pytam głównie o to, czy nie mógłbym leniwie użyć waszej walidacji :P

 

I tak z problemów, które jeszcze mi się czasem trafiają, bo już wiele z nich wyeliminowałem:

 

- najczęściej jest problem drobnej nadrealizacji partiami, pozycji zamówienia. Niektóre towary wydaje się z nadwyżką wagową/długościową, bo nie opłaca się ich ciąć. I tak np. mamy do wydania powiedzmy 8 metrów, i wydajemy po kolei w partiach 6,2m, 1,9m, 1,1m (tak dziwne liczby, ale to pikuś co tam logistyka potrafi wymyśleć). Co widzi NEXO, widzi że na zamówieniu było 8m, odejmuje 6,2m, czyli ma jeszcze 1,8m, odejmuje 1,9m, więc uważa, że ma zrealizowaną całość, a potem dostaje jeszcze po twarzy 1,1m do zamówienia, które uważa tą pozycję za zrealizowaną. Zmieniłem podejście i staram się sortować od najmniejszej długości te partie, ale magazynier i tak potrafi odwalić jakąś manianię. Dodam, że ze względów porządkowych, każda partia dodawana jest u nas, jako osobna pozycja - kwestie późniejszych użycia powiązań i jednoznacznego wskazania LP z WZ.

 

- ostatnio mamy przypadki z Nie można zrealizować zamówień ponieważ co najmniej jedno z nich jest zablokowane do realizacji, tutaj najczęście proforma, bez podpiętej płatności blokuje wydanie tego i jestem świadom że mogę to znaleźć w bazie.

 

Czyli jeśli dobrze zrozumiałem, mogę wywołać WypiszBledy na nie zapisanym obiekcie i on właśnie wtedy zrobi mi walidację?

 

 

Link to postu

Od razu odpowiem na to główne pytanie:

Cytat

mogę wywołać WypiszBledy na nie zapisanym obiekcie i on właśnie wtedy zrobi mi walidację?

Tak, może Pan wywołać WypiszBledy w każdym momencie i nie, nie wywoła on walidacji tylko zrobi dokładnie to na co wskazuje nazwa tej funkcji - wypisze aktualnie ustawione błędy. Walidacje są uruchamiane w kodzie programu wtedy kiedy są potrzebne i programista sferyczny z reguły nie ma wpływu na to kiedy dana walidacja zostanie uruchomiona. Oczywiście tak jak napisałem wcześniej istnieją wyjątki kiedy walidacja uruchamiana jest na zapisie obiektu (z reguły są to "ciężkie" walidacje, których świadomie nie chcemy uruchamiać w trakcie obróbki obiektu ze względu na wydajność). Wtedy faktycznie WypiszBledy nie zwróci nic, Zapisz zwróci false i dopiero po próbie zapisania WypiszBledy pokaże dokładny powód blokady zapisu.

Co do Pańskich przykładów to przyznam, że pierwszego problemu trochę nie rozumiem bo gdzie tu jest faktycznie błąd (poza oczywiście problemem, że zostało wydane więcej niż na ZK, ale z punktu widzenia nexo to nie jest błąd bo oczywiście można zapisać np. FS z ilością 20, która realizuje ZK z ilością 10)?

W drugim przypadku nie powstaje błąd biznesowy tylko jest rzucany wyjątek, który należy wyłapać. Przypadek "blokady realizacji" jest specyficzny bo realizacja zamówienia bez wymaganej wpłaty nie powinna w ogóle powstać więc zdecydowano, że przy próbie realizacji takiego zamówienia będzie rzucany wyjątek żeby nie dało się nic więcej zrobić. Tutaj WypiszBledy w ogóle nie pokaże tego komunikatu bo on nie jest "błędem biznesowym", a jak wspomniałem na początku "wyjątkiem".

Link to postu
12 godzin temu, Wojciech Szopiński napisał:

Co do Pańskich przykładów to przyznam, że pierwszego problemu trochę nie rozumiem bo gdzie tu jest faktycznie błąd (poza oczywiście problemem, że zostało wydane więcej niż na ZK, ale z punktu widzenia nexo to nie jest błąd bo oczywiście można zapisać np. FS z ilością 20, która realizuje ZK z ilością 10)?

Tak jak Pan napisał to nie było by problemu. Jak wspomniałem, u nas każda partia, to osobna pozycja w realizacji, więc realizujemy np. 7 sztuk, potem kolejna pozycja 7 sztuk z tego samego ZK, a potem 6 sztuk już się wysypuje, bo 14 nam to ZK zrealizowało :)

12 godzin temu, Wojciech Szopiński napisał:

W drugim przypadku nie powstaje błąd biznesowy tylko jest rzucany wyjątek, który należy wyłapać. Przypadek "blokady realizacji" jest specyficzny bo realizacja zamówienia bez wymaganej wpłaty nie powinna w ogóle powstać więc zdecydowano, że przy próbie realizacji takiego zamówienia będzie rzucany wyjątek żeby nie dało się nic więcej zrobić. Tutaj WypiszBledy w ogóle nie pokaże tego komunikatu bo on nie jest "błędem biznesowym", a jak wspomniałem na początku "wyjątkiem".

Yhym, czyli jednak muszę takie przypadki eliminować sam wcześniej, bo nie ukrywam, że właśnie te wyjątki, to już jedyne, jakie czasem mi sypną temat.

 

Link to postu
11 godzin temu, Radomił Ząbik napisał:

a potem 6 sztuk już się wysypuje

I rozumiem, że powodem "wysypania" jest po prostu status zamówienia, które jest już zrealizowane, tak? Wystarczy przed wywołaniem WypelnijNaPodstawieZK sprawdzić flagę DokumentZK.Zamkniety. W przypadku próby realizacji zamkniętego ZK również leci wyjątek i nie jest nakładny błąd biznesowy więc nie ma szans na obsłużenie tego przez WypiszBledy. Na początku ciągle uparcie szukałem tutaj błędów biznesowych (bo od początku Pan wspominał o WypiszBledy) i sądziłem, że chodzi o jakiś problem z wykonaniem ruchu magazynowego. Wtedy faktycznie WypiszBledy pokazałoby co jest problemem. Nadmienię jeszcze, że w celu obsługi błędów niepoprawnego ruchu magazynowego można skorzystać z interfejsu IBraki np. tak:

IWydanieZewnetrzne wydanieZewnetrzne;
//...
if (wydanieZewnetrzne.Braki.PosiadaBraki)
{
	IEnumerable<IBrakujacaPozycja> listaBrakow = wydanieZewnetrzne.Braki.Lista;
}

 

11 godzin temu, Radomił Ząbik napisał:

czyli jednak muszę takie przypadki eliminować sam

Tutaj wystarczy sprawdzić przed realizacją flagę DokumentZK.BlokujRealizacje.

  • Dziękuję 1
Link to postu
4 godziny temu, Wojciech Szopiński napisał:

Na początku ciągle uparcie szukałem tutaj błędów biznesowych (bo od początku Pan wspominał o WypiszBledy) i sądziłem, że chodzi o jakiś problem z wykonaniem ruchu magazynowego.

Może źle sformułowałem, użyłem WypiszBledy, bo to znam z waszego SDK, a nie wnikałem tak bardzo w różnicę pomiędzy błędem a wyjątkiem ;)

Dziękuje bardzo, za doinformowanie, będzie mi teraz łatwiej zaprojektować walidacje i rozwiązać jakoś problem szalonych magazynierów.

Link to postu
×
×
  • Dodaj nową pozycję...