Skocz do zawartości

[SFERA] Montaż zestawu z rozbiciem pozycji na partie

Polecane posty

Dzień Dobry,

 

Mam problemy przy tworzeniu zleceń montażu kompletów.

 

Dokładnie to tworzę aplikację do przechowywania informacji o zestawach komputerowych, ich stanie fizycznym złożenia, jakie części wchodzą w skład i dodatkowe informacje.

 

Finalnie aplikacja wysyła dany zestaw do Nexo - tworzy odpowiedni wpis do asortymentu i następnie tworzy zlecenie montażowe zgodne z odpowiadającym mu asorymentem.

 

Części mające numer seryjny (w subiekcie numery seryjne są przechowane jako kod dostawy) są wybierane z odpowiedniej partii. Reszta elementów leci wg ustawień subiekta (fifo,lifo itp itd).

 

Jednak za każdym razem przy zapisie takiego dokumentu dostaje błąd.

Poniżej przedstawiam kod

 

public bool MontujKomplet()
        {
            IZleceniaProdukcyjneMontowania izpm = Globals.sfera.PodajObiektTypu<IZleceniaProdukcyjneMontowania>();
            IAsortymenty asortymenty = Globals.sfera.PodajObiektTypu<IAsortymenty>();
            Asortyment aso = asortymenty.Dane.Wszystkie().Where(x=> x.Nazwa == "Zestaw komputerowy ARSO nr " + wybrany.numer).First();
            Konfiguracja konf = Globals.sfera.PodajObiektTypu<IKonfiguracje>().DaneDomyslne.ZlecenieProdukcyjneMontowania;
            Magazyn magZr = Globals.sfera.PodajObiektTypu<IMagazyny>().Dane.Wszystkie().Where(m => m.Symbol == "ARSO").FirstOrDefault();
            int pozKomplet = 1;

            using ( IZlecenieProdukcyjneMontowania zpm = izpm.Utworz(konf))
            {
                zpm.Dane.Magazyn = magZr;
             //  zpm.Dane.PozycjaKomplet
                IDokumentZRozbiciem dok = (IDokumentZRozbiciem)zpm;
                foreach (Pozycja poz in wybrany.pozycje)
                {
                    if (poz.idAsoNexo != 0)
                    {

                        Asortyment a = asortymenty.Dane.Wszystkie().Where(t => t.Id == poz.idAsoNexo).First();
                        if (a != null)
                        {
                            var tmp = zpm.PozycjeSkladniki.Dodaj(a, poz.ilosc, a.JednostkaSprzedazy);
                           // tmp.PozycjaKomplet = 
                            tmp.Ilosc = poz.ilosc;
                            tmp.IloscSumaryczna = poz.ilosc;
                            tmp.Cena.NettoPrzedRabatem = 0;
                            if (poz.nrSer.Trim() != "" && poz.nrSer.Trim() != "n/d")
                            {
                                var r = dok.RozpocznijRozbicieRozchodowe(tmp) as IRozbiciePozycjiRozchodowe;
                                r.Pozycje.Where(p => p.KodDostawy.ToLower().Contains(poz.nrSer.Trim().ToLower())).FirstOrDefault().Ilosc = poz.ilosc;
                                // var cena= r.Pozycje.Where(p => p.KodDostawy.ToLower().Contains(poz.nrSer.Trim().ToLower())).FirstOrDefault().CenaNabycia;
                                r.ZakonczRozbicie();

                            }

                        }
                        pozKomplet++;
                    }
                }
                    zpm.Montuj(aso);
                if (zpm.Zapisz())
                {

                    Console.WriteLine(zpm.Dane.NumerWewnetrzny.PelnaSygnatura);
                    Console.WriteLine(zpm.Dane.NumerWewnetrzny.PelnaSygnatura);
                    return true;
                }
                else
                {
                    zpm.WypiszBledy();
                    //wyslijMail();
                  //  DodajPrzesuniecieOdroczone();
                    return false;
                }

            }

            return false;

        }

 

Błędy jakie dostaje:
 

Nie ustawiono powiązanego obiektu.
 na polach:
PozycjaSkladnik.PozycjaKomplet

 

Nie ustawiono powiązanego obiektu.
 na polach:
PozycjaSkladnik.PozycjaKomplet

 

 

Nie ustawiono terminu ważności partii.
 na polach:
SpecyfikacjaPozycji.Termin

Nie ustawiono numeru partii.
 na polach:
SpecyfikacjaPozycji.Numer

 

 

Pierwsze dwa nie potrafię dojść do tego co jest problemem - podobny fragment kodu działa w przypadku przesunięć magazynowych.

 

Następne dwa są pozycjami obowiązkowymi w przypadku asortymentu wg konfiguracji w subiekcie. Jednak nie jestem pewny jak w tym momencie robić pozycje asortymentu montowanego.

Link to postu

Proszę spróbować wykonać metodę Montuj przed dodawaniem pozycji. Powinna ona być zawsze wykonywana jako pierwsza. Należy również pamiętać, że metoda ta doda do dokumentu ZPM pozycje składników, które są zdefiniowane w kartotece kompletu więc przy dodawaniu pozycji trzeba zweryfikować czy dodawana pozycja nie została już dodana automatycznie.

Link to postu

Również przez rozbicie pozycji tylko trzeba utworzyć rozbicie pozycji przychodowe na pozycji kompletu. Ewentualnie można też jeśli w założeniu będzie to zawsze dokładnie 1 partia przychodowa to można zmodyfikować utworzoną automatycznie specyfikację pozycji w PozycjaDokumentu.SpecyfikacjePozycji.

Link to postu

Udało się utworzyć w końcu zlecenie montażu na pozycjach prostych bez rozbijania składników na partie.

 

Jednak kiedy chciałem już rozbić je na partie to dostałem poniższy błąd:

 

image.thumb.png.62db9853b87aa35e4b9cb4b4f1d17f84.png

 

 

 

 

kod:


 

public bool MontujKomplet()
        {
            IZleceniaProdukcyjneMontowania izpm = Globals.sfera.PodajObiektTypu<IZleceniaProdukcyjneMontowania>();
            IAsortymenty asortymenty = Globals.sfera.PodajObiektTypu<IAsortymenty>();
            Asortyment aso = asortymenty.Dane.Wszystkie().Where(x=> x.Nazwa == "Zestaw komputerowy ARSO nr " + wybrany.numer).First();
            Konfiguracja konf = Globals.sfera.PodajObiektTypu<IKonfiguracje>().DaneDomyslne.ZlecenieProdukcyjneMontowania;
            Magazyn magZr = Globals.sfera.PodajObiektTypu<IMagazyny>().Dane.Wszystkie().Where(m => m.Symbol == "ARSO").FirstOrDefault();
            int pozKomplet = 1;

            using ( IZlecenieProdukcyjneMontowania zpm = izpm.Utworz(konf))
            {
                zpm.Dane.Magazyn = magZr;
             //  zpm.Dane.PozycjaKomplet
                IDokumentZRozbiciem dok = (IDokumentZRozbiciem)zpm;
                

                zpm.Montuj(aso);
                
                var t = dok.RozpocznijRozbiciePrzyjeciowe(zpm.Dane.PozycjaKomplet) as IRozbiciePozycjiPrzyjeciowe;
                var pozycjakomplet = t.Pozycje.First();
                pozycjakomplet.Ilosc = 1;
                pozycjakomplet.KodDostawy = "0";
                pozycjakomplet.TerminWaznosci = DateTime.Now.AddYears(2);
                t.ZakonczRozbicie();
                foreach (Pozycja poz in wybrany.pozycje)
                {
                    if (poz.idAsoNexo != 0)
                    {

                        Asortyment a = asortymenty.Dane.Wszystkie().Where(t => t.Id == poz.idAsoNexo).First();
                        if (a != null)
                        {
                            var tmp = zpm.PozycjeSkladniki.Dodaj(a, 0, a.JednostkaSprzedazy);
                           // tmp.PozycjaKomplet = 

                            tmp.Cena.NettoPrzedRabatem = 0;
                            if (poz.nrSer.Trim() != "" && poz.nrSer.Trim() != "n/d")
                            {
                                var r = dok.RozpocznijRozbicieRozchodowe(tmp) as IRozbiciePozycjiRozchodowe;
                                r.Pozycje.Where(p => p.KodDostawy.ToLower().Contains(poz.nrSer.Trim().ToLower())).FirstOrDefault().Ilosc = poz.ilosc;
                               
                                // var cena= r.Pozycje.Where(p => p.KodDostawy.ToLower().Contains(poz.nrSer.Trim().ToLower())).FirstOrDefault().CenaNabycia;
                                r.ZakonczRozbicie();

                            }else
                            {
                                tmp.Ilosc = poz.ilosc;

                            }


                        }
                        pozKomplet++;
                    }
                }
                   
                if (zpm.Zapisz())
                {

                    Console.WriteLine(zpm.Dane.NumerWewnetrzny.PelnaSygnatura);
                    Console.WriteLine(zpm.Dane.NumerWewnetrzny.PelnaSygnatura);
                    return true;
                }
                else
                {
                    zpm.WypiszBledy();
                    //wyslijMail();
                  //  DodajPrzesuniecieOdroczone();
                    return false;
                }

            }

            return false;

        }

W momencie kiedy zmieniam na 1 ilość w  

 

var tmp = zpm.PozycjeSkladniki.Dodaj(a, 0, a.JednostkaSprzedazy);

 

to kod przechodzi dalej ale zgłasza się inny błąd:

 

 

image.png.219175526a47c335b557b6f71b377f0a.png

 

Edytowane przez Bartłomiej Warchoł
Link to postu

Pierwszy błąd faktycznie dotyczy sytuacji gdy na pozycji składnika jest ilość zerowa i ustawienie niezerowej ilości tak jak u Pana powinno rozwiązać problem. W drugim przypadku zapewne na pozycjach rozbicia nie ma pozycji o podanym numerze seryjnym co powoduje, że FirstOrDefault() zwraca null.

Link to postu

Tak również myślałem.

Jednak po dokładnym sprawdzeniu (informator -> stany -> wybrany odpowiedni magazyn -> i skopiowany numer seryjny dłuższym przytrzymaniem LPM) partia na 100% istnieje.

 

Również po stronie aplikacji mam dostępne tylko towary i partie, które w danym momencie są na magazynie dostępne (ten element przez kilka miesięcy działał bez zarzutu - wcześniej zamiast kompletów tworzył przesunięcia magazynowe). 

image.thumb.png.a6bd3f0cd46f492bcdfcc629fc91d309.png

 

 

image.thumb.png.528e7e3eb5bd7966b4f0748a439aad7d.png

 

 

W wyrażeniach kontrolnych widać nr seryjny oraz id  = te dane zgadzają się z tymi znalezionymi w subiekcie.

 

Link to postu

Poszedłem za Pana poszlaką i przeiterowałem po pozycjach i 1 co mi wpadło w oko to fakt, że widoczne było tylko 15 pozycji a wg subiekta powinno być 16. W kolumnie obok "dostępne" było już 14. Jednak nie mogłem nigdzie sprawdzić co powoduje, że 2 partie były gdzieś zadysponowane.

Po zmianie numeru seryjnego to zadziałało ale na następnym elemencie się wykrzaczyło z tego samego powodu.

 

Koniec końców pozmieniałem wszystkie numery seryjne w testowym komplecie i udało mi się zlecenie montażu dokończyc.

 

Być może wiele prób tworzenia tego samego zestawu spowodowało, że mi się gdzieś te partie poblokowały - na podmiocie testowym tylko ja pracuje więc wątpie by ktoś innymi dokumentami mi te partie zablokował.

Link to postu

Z Pana opisu wnioskuję, że wisiały w bazie niezatwierdzone dyspozycje co powodowało niedostępność partii w rozbiciu pozycji. Być może podczas debugowania i wystąpienia błędu ubijał Pan swoją aplikację przez co zadysponowane partie się nie zwalniały. W normalnej sytuacji gdy Subiekt zostanie zamknięty awaryjnie podczas wystawiania np. wydania zewnętrznego to istniejące dyspozycje powinny zniknąć po kilku minutach pracy. Istnienie niezatwierdzonych dyspozycji można sprawdzić poprzez wyciągnięcie z tabeli Rozchody rekordów z ustawioną wartością w kolumnie SesjaRezerwujaca.

  • Dziękuję 1
Link to postu

Dzień Dobry,

 

Teraz zauważyłem, że pomimo tego, że udało mi się bez błędu doprowadzić działanie programu do końca to zlecenia montażu tworzą się naprawdę dziwnie.

 

 

 

 public bool MontujKomplet()
        {
            IZleceniaProdukcyjneMontowania izpm = Globals.sfera.PodajObiektTypu<IZleceniaProdukcyjneMontowania>();
            IAsortymenty asortymenty = Globals.sfera.PodajObiektTypu<IAsortymenty>();
            Asortyment aso = asortymenty.Dane.Wszystkie().Where(x=> x.Nazwa == "Zestaw komputerowy ARSO nr " + wybrany.numer).First();
            Konfiguracja konf = Globals.sfera.PodajObiektTypu<IKonfiguracje>().DaneDomyslne.ZlecenieProdukcyjneMontowania;
            Magazyn magZr = Globals.sfera.PodajObiektTypu<IMagazyny>().Dane.Wszystkie().Where(m => m.Symbol == "ARSO").FirstOrDefault();
            int pozKomplet = 1;

            using ( IZlecenieProdukcyjneMontowania zpm = izpm.Utworz(konf))
            {
                zpm.Montuj(aso);
                zpm.Dane.Magazyn = magZr;
                zpm.Dane.MagazynSkladnikow = magZr;
                zpm.Dane.DataPrzychodu = DateTime.Now;
                zpm.Dane.DataRozchodu = DateTime.Now;
             //  zpm.Dane.PozycjaKomplet
                IDokumentZRozbiciem dok = (IDokumentZRozbiciem)zpm;


               // zpm.Montuj(aso);

                var t = dok.RozpocznijRozbiciePrzyjeciowe(zpm.Dane.PozycjaKomplet) as IRozbiciePozycjiPrzyjeciowe;
                var pozycjakomplet = t.Pozycje.First();
                pozycjakomplet.Ilosc = 1;
                pozycjakomplet.KodDostawy = "0";
                pozycjakomplet.TerminWaznosci = DateTime.Now.AddYears(2);
                t.ZakonczRozbicie();
                foreach (Pozycja poz in wybrany.pozycje)
                {
                    if (poz.idAsoNexo != 0)
                    {

                        Asortyment a = asortymenty.Dane.Wszystkie().Where(t => t.Id == poz.idAsoNexo).First();
                        if (a != null)
                        {
                            var tmp = zpm.PozycjeSkladniki.Dodaj(a, 1, a.JednostkaSprzedazy);

                           // tmp.PozycjaKomplet = 

                            tmp.Cena.NettoPrzedRabatem = 0;
                            if (poz.nrSer.Trim() != "" && poz.nrSer.Trim() != "n/d")
                            {
                                var r = dok.RozpocznijRozbicieRozchodowe(tmp) as IRozbiciePozycjiRozchodowe;
                                r.Pozycje.Where(p => p.KodDostawy.ToLower().Contains(poz.nrSer.Trim().ToLower())).FirstOrDefault().Ilosc = poz.ilosc;
                               
                                // var cena= r.Pozycje.Where(p => p.KodDostawy.ToLower().Contains(poz.nrSer.Trim().ToLower())).FirstOrDefault().CenaNabycia;
                                r.ZakonczRozbicie();

                            }else
                            {
                                tmp.Ilosc = poz.ilosc;

                            }


                        }
                        pozKomplet++;
                    }
                }
                   
                if (zpm.Zapisz())
                {

                    Console.WriteLine(zpm.Dane.NumerWewnetrzny.PelnaSygnatura);
                    Console.WriteLine(zpm.Dane.NumerWewnetrzny.PelnaSygnatura);
                    return true;
                }
                else
                {
                    zpm.WypiszBledy();
                    //wyslijMail();
                  //  DodajPrzesuniecieOdroczone();
                    return false;
                }

            }

            return false;

        }

 

 

Przy montowaniu kompletu złożonego z dwóch elementów, gdzie jeden z nich wybierany jest FIFO automatycznie wg subiekta a drugi konkretną partię z numerem seryjnym.

 

efekt mam następujący:


image.thumb.png.c45d3e7899a067c998b787c263b5a827.png

 

 

Wydaje mi się, że czegoś nie rozumiem w jaki sposób działają te rozbicia z poziomu kodu.

Link to postu

Pisałem o tym w swoim pierwszym poście:

W dniu 2.03.2023 o 04:42, Wojciech Szopiński napisał:

Należy również pamiętać, że metoda ta doda do dokumentu ZPM pozycje składników, które są zdefiniowane w kartotece kompletu więc przy dodawaniu pozycji trzeba zweryfikować czy dodawana pozycja nie została już dodana automatycznie.

Dokładnie tak samo zachowuje się program - po dodaniu do dokumentu ZPM pozycji kompletu automatycznie dodają się pozycje składników wskazanych w kartotece kompletu.

Co do "podwojonej" ilości na ostatniej pozycji to Pana kod zwiększył ilość na wybranej partii rozbicia pozycji, ale nie została wyzerowana ilość na partii, która została wybrana wg kolejki (domyślnie FIFO). Dokładnie tak samo zachowuje się program - jeśli wejdzie Pan w rozbicie pozycji i zwiększy ilość na wybranej partii to ilość na pozycji się zwiększa gdyż program rozchoduje partie wybrane przez kolejkę oraz dodatkowo partię wskazaną przez operatora.

Edytowane przez Wojciech Szopiński
Link to postu

Rozumiem.

Czyli w takim razie albo na samym początku wyczyszczę listę asortymentów albo wyedytować istniejące.

 

1. Moja pierwsza próba "wyczyszczenia listy pozycji"

var t = dok.RozpocznijRozbiciePrzyjeciowe(zpm.Dane.PozycjaKomplet) as IRozbiciePozycjiPrzyjeciowe;
                var pozycjakomplet = t.Pozycje.First();
                pozycjakomplet.Ilosc = 1;
                pozycjakomplet.KodDostawy = "0";
                pozycjakomplet.TerminWaznosci = DateTime.Now.AddYears(2);
                t.ZakonczRozbicie();
                zpm.Dane.Pozycje.Clear();



Powoduje, że później var r = dok.RozpocznijRozbicieRozchodowe(tmp) as IRozbiciePozycjiRozchodowe; powoduje błąd niejednoznacznego rozbicia pozycji.

 

2. Otwarcie przyznam, że nie wiem w jaki sposób miałbym wyedytować te pozycje bym później mógł je jeszcze rozbić.

Link to postu

Ale tutaj:

51 minut temu, Bartłomiej Warchoł napisał:

zpm.Dane.Pozycje.Clear();

usuwa Pan wszystkie pozycje dokumentu ZPM włącznie z pozycją kompletu. Usunąć trzeba wszystkie pozycje typu PozycjaSkladnik po wykonaniu metody Montuj, np. tak:

// .ToArray() jest istotne gdyż bez tego wewnątrz pętli zmieni się kolekcja, na której
// operuje enumerator i zostanie wyrzucony wyjątek z informacją o zmodyfikowanej kolekcji
foreach (PozycjaSkladnik skladnik in zpm.Dane.Pozycje.OfType<PozycjaSkladnik>().ToArray())
  zpm.Dane.Pozycje.Remove(skladnik);

Czy nie rozważał Pan może ewidencjonowania kompletów w kartotece bez definiowania listy składników skoro w Pana przypadku i tak za każdym razem komplet może powstawać z różnych kartotek składników?

 

Co do edytowania pozycji rozbicia to wystarczy po prostu po rozpoczęciu rozbicia wyzerować (zmienić ilość na zero) pozycje rozbicia, które mają ilość większą od zera i potem można już zwiększać ilość na wybranej przez siebie pozycji. Jeszcze raz napiszę - wszystko tutaj wygląda dokładnie tak samo jak w programie.

  • Dziękuję 1
Link to postu
Cytat

Co do edytowania pozycji rozbicia to wystarczy po prostu po rozpoczęciu rozbicia wyzerować (zmienić ilość na zero) pozycje rozbicia, które mają ilość większą od zera i potem można już zwiększać ilość na wybranej przez siebie pozycji. Jeszcze raz napiszę - wszystko tutaj wygląda dokładnie tak samo jak w programie.

Z tym akurat sobie poradziłem dzięki Pana wskazówką i ilości już poprawnie mi się dodawały do montażu, Dlatego tej kwestii nie poruszyłem w poprzednim poście.

 

3 minuty temu, Wojciech Szopiński napisał:

usuwa Pan wszystkie pozycje dokumentu ZPM włącznie z pozycją kompletu. Usunąć trzeba wszystkie pozycje typu PozycjaSkladnik po wykonaniu metody Montuj,

Tu mnie zmylił podział na "Pozycje" i "PozycjeKompletu" - wyszedłem z założenia, że w takim razie pozycje to składniki. Teraz już wiem skąd ten mój błąd.

 

 

Co do ewidencji kompletów bez składników to nie wchodzi to u nas w grę.  Czym więcej informacji i śladów zostawi użytkownik tym lepiej można potem skontrolować co się w firmie dzieję.

 

 

Zastosowałem Pana kod i wszystko zaczęło działać poprawnie.

 

Bardzo dziękuję za pomoc :)

 

 

 

  • Lubię to 1
Link to postu
  • 1 rok później...

Zgłoszenie zostało zrealizowane w wersji 50.0.0. Fragment listy zmian:

  • W Sferze dla Subiekta nexo poprawiono błąd polegający na braku możliwości rozpoczęcia rozbicia pozycji zlecenia produkcyjnego, gdy miała ona zerową ilość.

  • W Sferze dla Subiekta nexo wprowadzono zabezpieczenie przed dodaniem pozycji składnika na dokumencie produkcyjnym przed zmontowaniem lub rozmontowaniem kompletu.

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