Skocz do zawartości

[Sfera] Zdarzeniowa, dostęp do realizowanych dokumentów, podczas tworzenia dokumentu


Zobacz rozwiązanie Rozwiązane przez Wojciech Szopiński,

Polecane posty

Chciałbym podczas tworzenia nowego dokumentu WZ, wprowadzić na niego jakieś informacje z ZK, które realizuje. W tym celu chciałem wykorzystać PoInicjalizacjiObiektu, ale żadna z metod na jakie wpadłem, nie zwraca żadnych powiązań z ZK, a może ich w tym momencie jeszcze nie ma ....

using InsERT.Moria.Archiwa;
using InsERT.Moria.Dokumenty.Logistyka;
using InsERT.Moria.ModelDanych;
using InsERT.Moria.Rozszerzanie;
using System;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Xml.Linq;

namespace TransferPolWlasnychDlaDokumentow
{
    public class DokumentSfera : KlientSferyZdarzeniowej<IWydanieZewnetrzne>
    {
         //// Metoda uruchamiana po stworzeniu nowego lub inicjacji istniejącego obiektu.
        public override void PoInicjalizacjiObiektu(IKontekstInicjalizacjiObiektu<IWydanieZewnetrzne> kontekst)
        {
            if (kontekst.StanObiektu == StanObiektu.Dodawany)
            {
                DokumentWZ wydanie = kontekst.ObiektBiznesowy.Dane;
                Debug.WriteLine("Dodawanie WZ rozpoczęte");
                var zk = wydanie.DokumentyRealizowane.Where(d => d.Symbol == "ZK").FirstOrDefault();
                if (zk != null)
                {
                    Debug.WriteLine("Pierwsze lepsze ZK " + zk.NumerWewnetrzny.PelnaSygnatura);
                }
                foreach (var dokument in wydanie.DokumentyPowiazane)
                {
                    Debug.WriteLine("Dokument powiązany " + dokument.NumerWewnetrzny.PelnaSygnatura);
                    Debug.WriteLine(dokument.GetType());
                }
                foreach (var dokument in wydanie.DokumentyRealizowane)
                {
                    Debug.WriteLine("Dokument realizowany "+dokument.NumerWewnetrzny.PelnaSygnatura);
                    Debug.WriteLine(dokument.GetType());
                }
                foreach (var dokument in wydanie.DokumentyRealizujace)
                {
                    Debug.WriteLine("Dokument realizujący " + dokument.NumerWewnetrzny.PelnaSygnatura);
                    Debug.WriteLine(dokument.GetType());
                }
            }
        }
    }
}

..., więc jeśli to kwestia, że ich nie ma, to zapewne trzeba by użyć PoZmianieWlasciwosciObiektu? Jeśli tak, to czy można ograniczyć jakoś wywołanie, aby nastąpiło tylko raz, po takim rzeczywistym utworzeniu dokumentu i wstępnie wypełnieniu go, wbudowanymi funkcjami - zarówno w Subiekt i Sferycznie - podczas jakiś prób, zauważyłem, że podpięcie pod tą metodę, jest używane wielokrotnie, pewnie przy każdym wypełnieniu, każdego pola w obiekcie.

Link to postu
2 godziny temu, Radomił Ząbik napisał:

W tym celu chciałem wykorzystać PoInicjalizacjiObiektu, ale żadna z metod na jakie wpadłem, nie zwraca żadnych powiązań z ZK

Powiązanie z dokumentami ZK będą standardowo dostępne przez kolekcję DokumentyRealizowane, ale...

2 godziny temu, Radomił Ząbik napisał:

a może ich w tym momencie jeszcze nie ma

... po inicjalizacji PUSTEGO obiektu WZ (i każdego innego dokumentu) ich tam jeszcze nie ma. Jakakolwiek realizacja polega na utworzeniu pustego obiektu dokumentu (wtedy jest wywoływane zdarzenie PoInicjalizacjiObiektu), a następnie wykonywana jest odpowiednia metoda WypelnijNaPodstawieXX.

 

2 godziny temu, Radomił Ząbik napisał:

więc jeśli to kwestia, że ich nie ma, to zapewne trzeba by użyć PoZmianieWlasciwosciObiektu?

To jest najlepsza ścieżka. Można zareagować na zmianę właściwości DokumentyRealizowane. Wadą tego podejścia jest oczywiście fakt, że to zdarzenie będzie się wywoływało tyle razy ile jest realizowanych dokumentów. Ewentualnie można też uzupełnić te dane przed zapisem obiektu. Wtedy będziemy mieli pewność, że nasza procedura "wypełniająca" wywoła się dokładnie raz z już wszystkimi dokumentami zrealizowanymi. Niemniej jednak ma również wady bo jeśli będziemy chcieli przed zapisem te zmiany zobaczyć na formatce to ich niestety nie zobaczymy przed zapisem obiektu.

2 godziny temu, Radomił Ząbik napisał:

czy można ograniczyć jakoś wywołanie, aby nastąpiło tylko raz, po takim rzeczywistym utworzeniu dokumentu i wstępnie wypełnieniu go, wbudowanymi funkcjami - zarówno w Subiekt i Sferycznie

Sfera zdarzeniowa w założeniu miała być na wysokim poziomie abstrakcji. Mechanizm ten nie wie jaki "biznes" jest pod spodem wykonywany. Jeśli miałoby coś takiego powstać to raczej byłby to punkt rozszerzenia czysto "Subiektowy" dla dokumentów w postaci funkcji wywoływanej "po wypełnieniu dokumentu, ale przed pokazaniem formatki", aczkolwiek nie rozważaliśmy implementacji takiego mechanizmu.

2 godziny temu, Radomił Ząbik napisał:

podczas jakiś prób, zauważyłem, że podpięcie pod tą metodę, jest używane wielokrotnie, pewnie przy każdym wypełnieniu, każdego pola w obiekcie.

Dokładnie tak jest, dlatego w kontekście przekazywana jest m.in. nazwa pola, które zostało "zmodyfikowane" dzięki czemu można zareagować tylko na zmiany interesujących nas własności obiektu.

Link to postu
2 godziny temu, Wojciech Szopiński napisał:

To jest najlepsza ścieżka. Można zareagować na zmianę właściwości DokumentyRealizowane. Wadą tego podejścia jest oczywiście fakt, że to zdarzenie będzie się wywoływało tyle razy ile jest realizowanych dokumentów.

Czyli tym razem, dobrze zrobiłem rozpoznanie ;)

2 godziny temu, Wojciech Szopiński napisał:

Ewentualnie można też uzupełnić te dane przed zapisem obiektu. Wtedy będziemy mieli pewność, że nasza procedura "wypełniająca" wywoła się dokładnie raz z już wszystkimi dokumentami zrealizowanymi. Niemniej jednak ma również wady bo jeśli będziemy chcieli przed zapisem te zmiany zobaczyć na formatce to ich niestety nie zobaczymy przed zapisem obiektu.

No właśnie nie chciałem iść "na łatwiznę" i uzupełnić to Sobie po zapisaniu, a właśnie uzupełnić przed pozostałymi zmianami, tak aby ewentualnie użytkownik widział już uzupełnioną formatkę i przypadkiem niepotrzebnie nie narobił się uzupełniając to, Sfera Zdarzeniowa zrobi za niego.

2 godziny temu, Wojciech Szopiński napisał:

Sfera zdarzeniowa w założeniu miała być na wysokim poziomie abstrakcji. Mechanizm ten nie wie jaki "biznes" jest pod spodem wykonywany. Jeśli miałoby coś takiego powstać to raczej byłby to punkt rozszerzenia czysto "Subiektowy" dla dokumentów w postaci funkcji wywoływanej "po wypełnieniu dokumentu, ale przed pokazaniem formatki", aczkolwiek nie rozważaliśmy implementacji takiego mechanizmu.

No właśnie w Sferze zdarzeniowej, podoba mi się to, że działa tu i tutaj. Szkoda by było utracić tą możliwość, nawet jeśli otrzymalibyśmy efekt "po otwarciu uzupełnionego okna".

3 godziny temu, Wojciech Szopiński napisał:

Dokładnie tak jest, dlatego w kontekście przekazywana jest m.in. nazwa pola, które zostało "zmodyfikowane" dzięki czemu można zareagować tylko na zmiany interesujących nas własności obiektu.

No trzeba będzie się podpinać pod jakieś mniej modyfikowane dane w takim razie.

 

Ok, to jutro wracam do projektowania rozwiązania. Generalnie w takim razie wyjaśnia mi się też, czemu nie miałem prawidłowej reakcji, jak próbowałem zrobić to bardziej uniwersalnie, poprzez IDokumenty - utworzony obiekt dokumentu, nie miał w tym momencie określonego typu dokumentu, więc dlatego walidacja typu mi nie przechodziła :)

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

To jest najlepsza ścieżka. Można zareagować na zmianę właściwości DokumentyRealizowane.

Zakładam, wzorując się na przykładach, że "zareagować na zmianę właściwości", to określić typ danych, dla kontekst.Dane? Wydawało mi się, że będę to mógł zrobić tak - zmieniłem podejście i idę od IDokument, aby rozwiązanie było bardziej uniwersalne:

public override void PoZmianieWlasciwosciObiektu(IKontekstZdarzeniaPoZmianieWlasciwosciObiektu<IDokument> kontekst)
{
if(kontekst.Dane is DokumentyRealizowane realizowane)
{
}
}

Niestety, nie ma tego obiektu. Dopiero jakbym określi dokładniej, że jest to np. DokumentWZ, to wiadomo, że dla niego będę miał potem DokumentyRealizowane, ale będę w sumie reagować na zmianę obiektu wydania, a nie samy realizacji dokumentów?

public override void PoZmianieWlasciwosciObiektu(IKontekstZdarzeniaPoZmianieWlasciwosciObiektu<IDokument> kontekst)
{
if(kontekst.Dane is DokumentWZ wydanie && wydanie.DokumentyRealizowane.Count!=0)
{
}
}

No chyba, że mnie poniosło i od IDokument nie da rady tego zrobić.

Link to postu
  • Rozwiązanie
5 minut temu, Radomił Ząbik napisał:

Zakładam, wzorując się na przykładach, że "zareagować na zmianę właściwości", to określić typ danych, dla kontekst.Dane?

Nie. W obiekcie typu IKontekstZdarzeniaPoZmianieWlasciwosciObiektu<T> w polu NazwaWlasciwosci jest przekazywana nazwa pola, która została zmodyfikowana i w obsłudze zdarzenia należy sprawdzić czy zostało zmienione pole, którego modyfikacja nas interesuje. Np. jeśli chcemy zmienić coś po zmianie sposobu dostawy na dokumencie to należałoby zrobić to np. tak:

public override void PoZmianieWlasciwosciObiektu(IKontekstZdarzeniaPoZmianieWlasciwosciObiektu<IDokument> kontekst)
{
  if (kontekst.NazwaWlasciwosci.Equals(nameof(Dokument.SposobDostawy)))
  {
    // zmieniono pole sposób dostawy - zróbmy coś z tym
  }
}

Można oczywiście "zahardkodować" nazwę właściwości w postaci stałego ciągu znaków "SposobDostawy", ale wyrażenie nameof() uodparnia kod na literówki.

W przypadku dokumentów realizowanych będzie analogicznie:

public override void PoZmianieWlasciwosciObiektu(IKontekstZdarzeniaPoZmianieWlasciwosciObiektu<IDokument> kontekst)
{
  if (kontekst.NazwaWlasciwosci.Equals(nameof(Dokument.DokumentyRealizowane)))
  {
    // zmieniono kolekcję dokumentów realizowanych - trzeba zareagować
  }
}

W tym momencie nasz kod będzie reagował na zmianę kolekcji DokumentyRealizowane dla każdego typu dokumentu (ponieważ klient sfery zdarzeniowej jest określony dla ogólnego typu IDokument). Jeśli chcemy np. zareagować na zmianę tej kolekcji tylko dla dokumentów wydań zewnętrznych to trzeba skorzystać z pola Dane w wyżej wspomnianym obiekcie typu IKontekstZdarzeniaPoZmianieWlasciwosciObiektu<T>. W polu tym jest przekazywana encja, która została zmodyfikowana. Oczywiście nie musi to być dokument bo np. gdy zostanie zmienione pole Ilosc na pozycji dokumentu to wtedy zostanie tam przekazana modyfikowana encja pozycji typu PozycjaDokumentu. Wtedy mogłoby to wyglądać tak:

public override void PoZmianieWlasciwosciObiektu(IKontekstZdarzeniaPoZmianieWlasciwosciObiektu<IDokument> kontekst)
{
  if (kontekst.NazwaWlasciwosci.Equals(nameof(Dokument.DokumentyRealizowane))
     && kontekst.Dane is DokumentWZ wz)
  {
    // zmieniono kolekcję dokumentów realizowanych wydania zewnętrznego - trzeba zareagować
  }
}

Dodatkowo jeszcze można sobie dodać warunki na rodzaj zmiany (przypisanie nowej wartości do pola, dodanie wartości do kolekcji, usunięcie wartości z kolekcji lub wyczyszczenie kolekcji) poprzez pole RodzajZmiany oraz sposób edycji obiektu (czy edycja została wykonana przez formatkę obiektu czy też w inny sposób np. operacją zbiorczą).

  • Lubię to 2
Link to postu

Dobra, jeszcze jedno pytanie, wiem, że pewnie ma Pan dosyć na dzisiaj ;) W normalnej Sferze, mamy zmienną sfera, z której mogę Sobie potem użyć ...

IPolaWlasneAdv2Accessor asoPW2Accessor = sfera.UtworzPolaWlasneAdv2Accessor(aso.Dane);

... i o ile dostęp do zwykłych obiektów jak podmioty, dokumenty, już Sobie znalazłem i wiem jak używać, to nie wiem, jak dostać się do Sfery. Nie wiem, jak przekazać Sobie "Sfere", już kombinowałem na kilka sposobów ;)

private readonly IUchwyt _uchwyt;
public DokumentSferaZdarzeniowaPlugin(IUchwyt uchwyt) { _uchwyt = uchwyt; }

 

Link to postu
Godzinę temu, Radomił Ząbik napisał:

Dobra, jeszcze jedno pytanie, wiem, że pewnie ma Pan dosyć na dzisiaj ;)

Jeszcze nie ;)

Godzinę temu, Radomił Ząbik napisał:

Nie wiem, jak przekazać Sobie "Sfere",

Uchwyt do sfery jest przekazywany w polu Uchwyt obiektu IKontekstZdarzeniaPoZmianieWlasciwosciObiektu<T>. Polecam dział Rozszerzanie/Punkty rozszerzania/Sfera zdarzeniowa w dokumentacji SDK :) 

Link to postu

Ok, racja, jest ...

kontekst.Uchwyt

... tylko, że jest to typ InsERT.Moria.Rozszerzanie.IUchwyt, a ja potrzebuję InsERT.Moria.Sfera.Uchwyt, aby można było użyć UtworzPolaWlasneAdv2Accessor i nie mam pojęcia jak to przekonwertować - tutaj kłania się w takim razie brak dostatecznej znajomości C#.

22 minuty temu, Wojciech Szopiński napisał:

Polecam dział Rozszerzanie/Punkty rozszerzania/Sfera zdarzeniowa w dokumentacji SDK

Znam, przeglądałem, akurat lepsze są przykłady i tam rzeczywiście są też przykłady z Uchwyt i możliwością wygodniejszego pobrania obiektów. Tylko nie mam pojęcia jak pobrać prawidłowo Sferę, aby można było dostać się do pół wlasnych 2.

Link to postu

Obiekt Uchwyt nie jest dostępny w pluginach oraz sferze zdarzeniowej i nie planujemy go udostępniać. W większości przypadków powinien wystarczyć IUchwyt, który jest przekazywany w kontekście zdarzenia sferycznego. Pola własne zaawansowane są dostępne w pluginach oraz sferze zdarzeniowej przy zastosowaniu takiej konstrukcji

var zaawansowanePolaWlasne = kontekst.Uchwyt.PodajObiektTypu<IPolaWlasneAdv2AccessorFactory>().Utworz(aso.Dane, true);

 

  • Dziękuję 1
Link to postu
×
×
  • Dodaj nową pozycję...