Manajemen parameter dalam aplikasi bisnis mirip dengan sistem kontrol versi

gambar

Dalam berbagai aplikasi, tugas muncul secara teratur untuk mendukung logika perubahan waktu dari beberapa atribut suatu objek relatif terhadap subjek tertentu (atau subjek). Misalnya, ini dapat berupa perubahan harga eceran barang di toko atau indikator KPI untuk karyawan.

Pada artikel ini, saya akan menunjukkan logika domain dan antarmuka apa yang dapat dibangun untuk menyelesaikan masalah ini. Saya akan segera membuat reservasi yang akan menyangkut pengaruh manajerial pengguna pada atribut, dan bukan refleksi dari perubahan historis.

Implementasi akan disajikan berdasarkan platform lsFusion terbuka dan gratis, tetapi skema serupa dapat diterapkan ketika menggunakan teknologi lainnya.

Pendahuluan


Untuk presentasi dan pemahaman artikel yang lebih sederhana, kami mengambil harga sebagai atribut, produk sebagai objek, dan gudang akan menjadi subjek. Dalam hal ini, interval minimum yang mungkin untuk mengatur atribut adalah tanggal. Dengan demikian, pengguna akan dapat menentukan berapa harga untuk tanggal tertentu akan untuk setiap produk dan gudang.

Skema input pengguna untuk perubahan harga akan serupa dengan yang digunakan dalam sistem kontrol versi klasik. Setiap perubahan, dari sudut pandang logika domain, akan menjadi komit tunggal, berdasarkan status status untuk tanggal tertentu akan dihitung. Di banyak bidang studi, komit semacam itu disebut dokumen atau transaksi. Dalam hal ini, dengan komit ini kita akan mengartikan apa yang disebut daftar harga. Setiap daftar harga akan menentukan barang dan gudang yang termasuk di dalamnya, serta masa berlakunya.

Skema yang dijelaskan memiliki keuntungan sebagai berikut:

  • Atomicity . Setiap perubahan dikeluarkan sebagai dokumen terpisah. Oleh karena itu, dokumen-dokumen ini dapat disimpan sementara, tetapi tidak diposting. Dengan input yang salah, mudah untuk memutar kembali seluruh perubahan.
  • Transparansi Sangat mudah untuk menentukan siapa yang membuat perubahan dan kapan, serta menunjukkan alasannya dengan membuat komentar pada dokumen.

Perbedaan utama dari sistem kontrol versi adalah bahwa commit eksplisit tidak tergantung satu sama lain. Dengan demikian, dimungkinkan untuk menghapus semua komit yang relatif tanpa rasa sakit kapan saja. Selain itu, setiap komit tersebut dapat diatur untuk berakhir ketika berhenti berfungsi, yang tentu saja tidak ada dalam sistem kontrol versi.

Implementasi


Kami mulai definisi logika domain dengan gudang. Mari kita sedikit mempersulit solusi dengan menggabungkan gudang ke dalam hierarki sekelompok kedalaman dinamis. Dengan prinsip apa ini dilakukan dijelaskan dalam artikel terkait, jadi saya hanya akan memberikan sepotong kode yang menyatakan grup dan membuat formulir untuk mengeditnya:

Pengumuman Kelompok Gudang
CLASS Group ' ' ;
name '' = DATA ISTRING [ 50 ] (Group);

parent = DATA Group (Group);
nameParent ' ' (Group g) = name(parent(g));

level '' (Group child, Group parent) =
RECURSION 1l IF child IS Group AND parent = child
STEP 2l IF parent = parent($parent) MATERIALIZED ;

FORM group ' '
OBJECTS g = Group PANEL
PROPERTIES (g) name, nameParent

EDIT Group OBJECT g
;

FORM groups ' '
OBJECTS g = Group
PROPERTIES (g) READONLY name, nameParent
PROPERTIES (g) NEWSESSION NEW , EDIT , DELETE

LIST Group OBJECT g
;

NAVIGATOR {
NEW groups;
}

Contoh hierarki grup
gambar


Selanjutnya, nyatakan gudang yang dapat diikat ke salah satu grup:

Pengumuman Gudang
CLASS Stock '' ;
name '' = DATA ISTRING [ 50 ] (Stock);

group '' = DATA Group (Stock);
nameGroup '' (Stock st) = name(group(st));

FORM stock ''
OBJECTS s = Stock PANEL
PROPERTIES (s) name, nameGroup

EDIT Stock OBJECT s
;

FORM stocks ''
OBJECTS s = Stock
PROPERTIES (s) READONLY name, nameGroup
PROPERTIES (s) NEWSESSION NEW , EDIT , DELETE

LIST Stock OBJECT s
;

NAVIGATOR {
NEW stocks;
}


Contoh Gudang
gambar


Dan akhirnya, nyatakan logika barang:

Pengumuman Produk
CLASS Product '' ;
name '' = DATA ISTRING [ 50 ] (Product);

FORM product ''
OBJECTS p = Product PANEL
PROPERTIES (p) name

EDIT Product OBJECT p
;

FORM products ''
OBJECTS p = Product
PROPERTIES (p) READONLY name
PROPERTIES (p) NEWSESSION NEW , EDIT , DELETE

LIST Product OBJECT p
;

NAVIGATOR {
NEW products;
}

Contoh produk
gambar


Kami melanjutkan langsung ke pembuatan logika daftar harga. Pertama, kami menetapkan kelas daftar harga itu sendiri, serta periode validitasnya:
CLASS PriceList '-' ;
fromDate ' ' = DATA DATE (PriceList);
toDate ' ' = DATA DATE (PriceList);
Kami percaya bahwa jika tidak ada Tanggal yang ditetapkan, maka daftar harga tidak ada habisnya.
Kami menambahkan acara yang, ketika membuat daftar harga, secara otomatis akan mencantumkan tanggal saat ini dari mana ia akan mulai beroperasi.
WHEN LOCAL SET (PriceList p IS PriceList) DO
fromDate(p) <- currentDate();
Kata kunci LOCAL berarti bahwa acara tersebut tidak akan diaktifkan ketika save diterapkan ke basis data, tetapi segera ketika perubahan dilakukan.

Kemudian tambahkan pengguna yang membuatnya dan waktu pembuatan:
createdTime ' ' = DATA DATETIME (PriceList);
createdUser = DATA User (PriceList);
nameCreatedUser '' (PriceList p) = name(createdUser(p));
Sekarang buat acara yang secara otomatis mengisinya:
WHEN SET (PriceList p IS PriceList) DO {
createdTime(p) <- currentDateTime();
createdUser(p) <- currentUser();
}
Acara ini, tidak seperti yang sebelumnya, akan dipicu hanya ketika tombol Simpan diklik. Artinya, selama transaksi simpan ke database.

Selanjutnya, buat garis daftar harga di mana barang dan harga akan ditetapkan:
CLASS PriceListDetail ' -' ;
priceList = DATA PriceList (PriceListDetail) NONULL DELETE ;

product = DATA Product (PriceListDetail);
nameProduct '' (PriceListDetail d) = name(product(d));

price '' = DATA NUMERIC [ 10 , 2 ] (PriceListDetail);
Atribut NONULL menunjukkan bahwa properti priceList harus selalu ditetapkan, dan DELETE menunjukkan bahwa ketika nilai properti di-zeroed (misalnya, ketika menghapus daftar harga), baris yang sesuai harus dihapus secara otomatis.

Untuk penggunaan di masa mendatang, kami akan membuat properti yang akan menentukan periode validitas garis daftar harga:
fromDate ' ' (PriceListDetail d) = fromDate(priceList(d));
toDate ' ' (PriceListDetail d) = toDate(priceList(d));
Sekarang kita akan mengikat daftar harga ke gudang yang akan dioperasikan. Pertama, tambahkan properti utama, yang akan menjadi kenyataan jika seluruh kelompok gudang termasuk dalam daftar harga:
dataIn '' = DATA BOOLEAN (PriceList, Group);
Kami menghitung "inklusi" grup dengan mempertimbangkan orang tua yang dipilih (seperti yang dijelaskan dalam artikel tentang hierarki):
in ' ()' (PriceList p, Group child) =
GROUP LAST dataIn(p, Group parent) ORDER DESC level(child, parent) WHERE dataIn(p, parent);
Tambahkan properti utama, yang dengannya Anda dapat menentukan bahwa daftar harga bertindak pada gudang tertentu:
dataIn '' = DATA BOOLEAN (PriceList, Stock);
Kami menghitung properti akhir, yang akan menentukan bahwa daftar harga mengubah harga di gudang terkait, dengan mempertimbangkan grup:
in '' (PriceList p, Stock s) = dataIn(p, s) OR in(p, group(s));
Buat properti yang akan menampilkan nama semua grup dan gudang yang dipilih dari daftar harga, untuk pengguna yang lebih nyaman untuk melihat daftar daftar harga:
stocks '' (PriceList p) = CONCAT ' / ' ,
GROUP CONCAT name(Group g) IF dataIn(p, g), ',' ORDER g,
GROUP CONCAT name(Stock s) IF dataIn(p, s), ',' ORDER s
CHARWIDTH 30 ;
Langkah terakhir dalam deskripsi logika domain akan secara langsung menghitung harga barang saat ini di gudang. Untuk melakukan ini, buat properti yang menemukan baris terakhir berdasarkan tanggal pada daftar harga dengan barang, gudang, dan masa berlaku yang diinginkan:
priceListDetail (Product p, Stock s, DATE dt) =
GROUP LAST PriceListDetail d
ORDER fromDate(d), d
WHERE product(d) = p AND in(priceList(d), s) AND
fromDate(d) <= dt AND NOT toDate(d) < dt;
Dalam logika penghitungan properti ini, berbagai variasi dimungkinkan. Anda dapat mengubah filter untuk memukul baris (misalnya, menambahkan kondisi di WHERE bahwa daftar harga diposting) dan pesanan. Perlu dicatat bahwa objek itu sendiri, atau lebih tepatnya pengenal internalnya, telah ditambahkan ke urutan pemilihan oleh parameter kedua. Ini diperlukan agar nilai harga selalu ditentukan dengan cara yang unik.

Berdasarkan garis daftar harga yang diterima, kami menentukan nilai harga dan masa berlakunya:
price '' (Product p, Stock s, DATE dt) = price(priceListDetail(p, s, dt));
fromDate ' ' (Product p, Stock s, DATE dt) = fromDate(priceListDetail(p, s, dt));
toDate ' ' (Product p, Stock s, DATE dt) = toDate(priceListDetail(p, s, dt));
Mereka akan lebih lanjut digunakan dalam tabel antarmuka pengguna.

Selanjutnya, kita beralih ke membangun antarmuka pengguna. Pertama, kami menggambar formulir untuk mengedit daftar harga. Buat formulir dan tambahkan "header" dari dokumen di sana:
FORM priceList '-'
OBJECTS p = PriceList PANEL
PROPERTIES (p) fromDate, toDate

EDIT PriceList OBJECT p
;
Tambahkan baris daftar harga ke formulir:
EXTEND FORM priceList
OBJECTS d = PriceListDetail
PROPERTIES (d) nameProduct, price
PROPERTIES (d) NEW , DELETE
FILTERS priceList(d) = p
;
Selanjutnya, tambahkan pohon di mana akan ada grup dan gudang:
EXTEND FORM priceList
TREE stocks g = Group PARENT parent, s = Stock
PROPERTIES READONLY name(g), name(s)
PROPERTIES dataIn(p, g), in(p, g)
PROPERTIES dataIn(p, s), in(p, s)
FILTERS group(s) = g
;
Properti untuk grup dan gudang ditambahkan ke pohon secara bersamaan. Platform akan, tergantung pada objek, menunjukkan properti ini atau itu dalam urutan mereka ditambahkan ke formulir.

Kami menyesuaikan desain formulir sehingga barang dan gudang digambar dalam tab terpisah:
DESIGN priceList {
OBJECTS {
NEW pane {
fill = 1 ;
type = TABBED ;
MOVE BOX (d) { caption = '' ; }
MOVE BOX ( TREE stocks) { caption = '' ; }
}
}
}
Formulir edit akan terlihat seperti ini:

gambar

gambar

Tetap membangun bentuk dasar manajemen harga. Ini akan terdiri dari dua tab. Yang pertama akan menampilkan daftar semua daftar harga (mirip dengan daftar commit). Tab kedua akan menampilkan harga saat ini untuk gudang tertentu untuk tanggal yang dipilih.

Untuk menerapkan tab pertama, tambahkan ke formulir daftar daftar harga dengan garis untuk pratinjau cepat:
FORM managePrices ' '
OBJECTS p = PriceList
PROPERTIES (p) READONLY fromDate, toDate, stocks, createdTime, nameCreatedUser
PROPERTIES (p) NEWSESSION NEW , EDIT , DELETE

OBJECTS d = PriceListDetail
PROPERTIES (d) READONLY nameProduct, price
FILTERS priceList(d) = p
;
Untuk tab kedua, pertama-tama kita tambahkan tanggal di mana harga ditampilkan, pohon kelompok gudang, serta gudang itu sendiri:
EXTEND FORM managePrices
OBJECTS dt = DATE PANEL
PROPERTIES VALUE (dt)

TREE groups g = Group PARENT parent
PROPERTIES READONLY name(g)

OBJECTS s = Stock
PROPERTIES (s) READONLY name, nameGroup
FILTERS level(group(s), g)
;
Daftar gudang akan menunjukkan semua gudang yang merupakan keturunan dari kelompok yang dipilih di bagian atas.

Selanjutnya, tambahkan ke formulir daftar barang yang ada harga valid untuk gudang pada tanggal yang dipilih:
EXTEND FORM managePrices
OBJECTS pr = Product
PROPERTIES READONLY name(pr), price(pr, s, dt), fromDate(pr, s, dt), toDate(pr, s, dt)
FILTERS price(pr, s, dt)
;
Baik harga itu sendiri maupun masa berlakunya ditambahkan ke kolom. Anda juga dapat menambahkan nomor daftar harga - maka tabel ini akan menyerupai logika anotasi dalam sistem kontrol versi.

Agar pengguna memahami dari mana harga tersebut berasal, kami menambahkan daftar garis daftar harga dengan barang dan gudang yang sesuai:
EXTEND FORM managePrices
OBJECTS prd = PriceListDetail
PROPERTIES READONLY BACKGROUND (priceListDetail(pr, s, dt) = prd)
fromDate(prd), toDate(prd), '' = stocks(priceList(prd)), price(prd)
FILTERS product(prd) = pr AND in(priceList(prd), s)
;
Menggunakan atribut BACKGROUND, sorot baris yang menentukan harga yang ditunjukkan pada tabel.

Juga, untuk kenyamanan pengguna, kami akan menambahkan kemampuan untuk membuka formulir edit dari daftar harga yang sesuai dalam sesi baru langsung dari cerita ini:
edit (PriceListDetail d) + { edit(priceList(d)); }
EXTEND FORM managePrices
PROPERTIES (prd) NEWSESSION EDIT
;
Untuk mencapai ini, Anda perlu menentukan tindakan yang akan dilakukan ketika Anda mencoba mengedit garis dengan menerapkan tindakan edit bawaan. Kemudian, tombol standar untuk mengedit objek melalui panggilan dialog ditambahkan ke formulir dengan cara standar.

Dan akhirnya, kami membentuk desain akhir dari formulir:
DESIGN managePrices {
OBJECTS {
NEW pane {
fill = 1 ;
type = TABBED ;
NEW priceLists {
caption = '-' ;
MOVE BOX (p);
MOVE BOX (d);
}
NEW prices {
caption = '' ;
fill = 1 ;
type = SPLITH ;
NEW leftPane {
MOVE BOX (dt);
MOVE BOX ( TREE groups);
MOVE BOX (s);
}
NEW rightPane {
fill = 3 ;
type = SPLITV ;
MOVE BOX (pr) { fill = 3 ; }
MOVE BOX (prd);
}
}
}
}
}
Di sini, wadah pane ditambahkan terlebih dahulu, yang terdiri dari dua tab: daftar harga dan harga . Yang pertama hanya menambahkan daftar daftar harga dan garis. Dalam yang kedua, dua panel dibuat: leftPane dan rightPane . Panel kiri berisi tanggal dan gudang, dan panel kanan berisi barang dan sejarah harga.

Hasil


Pertimbangkan opsi utama untuk menggunakan logika yang dihasilkan.

Misalkan kita memiliki dua daftar harga terpisah untuk berbagai kelompok barang. Kemudian, tergantung pada gudang yang dipilih, di tab dengan harga, hanya produk dari daftar harga yang sesuai yang akan ditampilkan:

gambar

Sekarang buat daftar harga baru dengan periode validitas terbatas, daftar gudang dan harga baru. Pada tab kedua, jika kita memilih tanggal di kisaran daftar harga baru, kita akan mendapatkan harga baru darinya. Segera setelah masa berlaku berakhir, harga lama akan kembali dari harga aslinya:

gambar

Dengan menggunakan mekanisme yang sama, Anda dapat "membatalkan" aksi harga tertentu dari tanggal tertentu. Misalnya, jika Anda memasukkan harga baru tanpa menentukan harga, ternyata harga akan diatur ulang dan barang akan hilang dari filter. Dalam hal ini, saat menghapus dokumen yang dimasukkan, semuanya kembali ke keadaan lama:

gambar

Properti yang dihasilkan dengan harga barang oleh gudang pada tanggal dapat digunakan lebih lanjut dalam berbagai acara atau bentuk lainnya. Misalnya, Anda dapat membuat penetapan harga otomatis dalam urutan berdasarkan pada logika penetapan harga ini:
WHEN LOCAL CHANGED (sku(UserOrderDetail d)) OR CHANGED (stock(d)) OR CHANGED (dateTime(d)) DO
price(d) <- price(sku(d), stock(d), dateTime(d));
Bonus bagus dalam logika ini adalah bahwa ketika Anda menambahkan gudang baru ke grup, harga dari daftar harga yang sudah dibuat akan secara otomatis berlaku untuk itu. Hal yang sama akan terjadi ketika Anda mengubah grup untuk gudang.

Jika mau, Anda dapat membuat kolom dengan harga di tab dengan harga saat ini dapat diedit dan menambahkan tombol yang akan membuat komit baru untuk perubahan harga.

Kesimpulan


Dalam solusi di tingkat platform, tidak ada buku referensi, atau dokumen dengan string, atau register, atau laporan dan abstraksi lain yang tidak perlu digunakan. Semuanya dilakukan secara eksklusif pada konsep kelas dan properti. Perhatikan bahwa logika yang cukup rumit ini diterapkan di sekitar 150 baris kode yang bermakna di lsFusion. Untuk mengimplementasikannya dalam formulasi yang sama di platform lain (misalnya, 1C) adalah tugas yang jauh lebih sulit.

Skema yang dijelaskan di atas banyak digunakan dalam solusi ERP berbasis lsFusion. Dengan menggunakannya, dengan berbagai modifikasi, daftar harga pemasok, harga eceran manajemen, stok, dan banyak parameter manajemen lainnya didukung.

Templat dapat menjadi rumit dengan menambahkan beberapa entitas ke dokumen (misalnya, pemasok dapat ditambahkan ke gudang), serta mendefinisikan beberapa atribut dalam satu dokumen sekaligus. Secara khusus, Anda bisa menambahkan Tipe Harga entitas, dan di baris dokumen setel harga untuk tupel baris dan tipe harga yang sesuai. Dalam logika yang dijelaskan di atas, Anda hanya perlu menambahkan beberapa parameter tambahan ke beberapa properti.

Dengan bantuan beberapa baris kode tambahan, dimungkinkan untuk mendenormalisasi semua catatan perubahan ke dalam satu tabel untuk membangun indeks yang sesuai. Maka pemilihan nilai apa pun untuk tanggal apa pun akan dilakukan dalam waktu logaritmik. Optimalisasi seperti itu diperlukan ketika ada beberapa ratus juta catatan dalam tabel ini.

Anda dapat mencoba contoh buatannya secara online pada halaman situs yang bersangkutan (bagian Platform). Berikut ini seluruh kode sumber yang harus Anda tempelkan ke bidang yang diinginkan:

Kode sumber
REQUIRE Authentication, Time;

CLASS Group ' ' ;
name '' = DATA ISTRING [ 50 ] (Group);

parent = DATA Group (Group);
nameParent ' ' (Group g) = name(parent(g));

level '' (Group child, Group parent) =
RECURSION 1l IF child IS Group AND parent = child
STEP 2l IF parent = parent($parent) MATERIALIZED ;

FORM group ' '
OBJECTS g = Group PANEL
PROPERTIES (g) name, nameParent

EDIT Group OBJECT g
;

FORM groups ' '
OBJECTS g = Group
PROPERTIES (g) READONLY name, nameParent
PROPERTIES (g) NEWSESSION NEW , EDIT , DELETE

LIST Group OBJECT g
;

NAVIGATOR {
NEW groups;
}

CLASS Stock '' ;
name '' = DATA ISTRING [ 50 ] (Stock);

group '' = DATA Group (Stock);
nameGroup '' (Stock st) = name(group(st));

FORM stock ''
OBJECTS s = Stock PANEL
PROPERTIES (s) name, nameGroup

EDIT Stock OBJECT s
;

FORM stocks ''
OBJECTS s = Stock
PROPERTIES (s) READONLY name, nameGroup
PROPERTIES (s) NEWSESSION NEW , EDIT , DELETE

LIST Stock OBJECT s
;

NAVIGATOR {
NEW stocks;
}

CLASS Product '' ;
name '' = DATA ISTRING [ 50 ] (Product);

FORM product ''
OBJECTS p = Product PANEL
PROPERTIES (p) name

EDIT Product OBJECT p
;

FORM products ''
OBJECTS p = Product
PROPERTIES (p) READONLY name
PROPERTIES (p) NEWSESSION NEW , EDIT , DELETE

LIST Product OBJECT p
;

NAVIGATOR {
NEW products;
}

CLASS PriceList '-' ;
fromDate ' ' = DATA DATE (PriceList);
toDate ' ' = DATA DATE (PriceList);

createdTime ' ' = DATA DATETIME (PriceList);
createdUser = DATA User (PriceList);
nameCreatedUser '' (PriceList p) = name(createdUser(p));

WHEN LOCAL SET (PriceList p IS PriceList) DO
fromDate(p) <- currentDate();

WHEN SET (PriceList p IS PriceList) DO {
createdTime(p) <- currentDateTime();
createdUser(p) <- currentUser();
}

CLASS PriceListDetail ' -' ;
priceList = DATA PriceList (PriceListDetail) NONULL DELETE ;

product = DATA Product (PriceListDetail);
nameProduct '' (PriceListDetail d) = name(product(d));

price '' = DATA NUMERIC [ 10 , 2 ] (PriceListDetail);

fromDate ' ' (PriceListDetail d) = fromDate(priceList(d));
toDate ' ' (PriceListDetail d) = toDate(priceList(d));

dataIn '' = DATA BOOLEAN (PriceList, Group);

in ' ()' (PriceList p, Group child) =
GROUP LAST dataIn(p, Group parent) ORDER DESC level(child, parent) WHERE dataIn(p, parent);

dataIn '' = DATA BOOLEAN (PriceList, Stock);
in '' (PriceList p, Stock s) = dataIn(p, s) OR in(p, group(s));

stocks '' (PriceList p) = CONCAT ' / ' ,
GROUP CONCAT name(Group g) IF dataIn(p, g), ',' ORDER g,
GROUP CONCAT name(Stock s) IF dataIn(p, s), ',' ORDER s
CHARWIDTH 30 ;

priceListDetail (Product p, Stock s, DATE dt) =
GROUP LAST PriceListDetail d
ORDER fromDate(d), d
WHERE product(d) = p AND in(priceList(d), s) AND
fromDate(d) <= dt AND NOT toDate(d) < dt;

price '' (Product p, Stock s, DATE dt) = price(priceListDetail(p, s, dt));
fromDate ' ' (Product p, Stock s, DATE dt) = fromDate(priceListDetail(p, s, dt));
toDate ' ' (Product p, Stock s, DATE dt) = toDate(priceListDetail(p, s, dt));

FORM priceList '-'
OBJECTS p = PriceList PANEL
PROPERTIES (p) fromDate, toDate

EDIT PriceList OBJECT p
;

EXTEND FORM priceList
OBJECTS d = PriceListDetail
PROPERTIES (d) nameProduct, price
PROPERTIES (d) NEW , DELETE
FILTERS priceList(d) = p
;

EXTEND FORM priceList
TREE stocks g = Group PARENT parent, s = Stock
PROPERTIES READONLY name(g), name(s)
PROPERTIES dataIn(p, g), in(p, g)
PROPERTIES dataIn(p, s), in(p, s)
FILTERS group(s) = g
;

DESIGN priceList {
OBJECTS {
NEW pane {
fill = 1 ;
type = TABBED ;
MOVE BOX (d) { caption = '' ; }
MOVE BOX ( TREE stocks) { caption = '' ; }
}
}
}

FORM managePrices ' '
OBJECTS p = PriceList
PROPERTIES (p) READONLY fromDate, toDate, stocks, createdTime, nameCreatedUser
PROPERTIES (p) NEWSESSION NEW , EDIT , DELETE

OBJECTS d = PriceListDetail
PROPERTIES (d) READONLY nameProduct, price
FILTERS priceList(d) = p
;

EXTEND FORM managePrices
OBJECTS dt = DATE PANEL
PROPERTIES VALUE (dt)

TREE groups g = Group PARENT parent
PROPERTIES READONLY name(g)

OBJECTS s = Stock
PROPERTIES (s) READONLY name, nameGroup
FILTERS level(group(s), g)
;

EXTEND FORM managePrices
OBJECTS pr = Product
PROPERTIES READONLY name(pr), price(pr, s, dt), fromDate(pr, s, dt), toDate(pr, s, dt)
FILTERS price(pr, s, dt)
;

EXTEND FORM managePrices
OBJECTS prd = PriceListDetail
PROPERTIES READONLY BACKGROUND (priceListDetail(pr, s, dt) = prd)
fromDate(prd), toDate(prd), '' = stocks(priceList(prd)), price(prd)
FILTERS product(prd) = pr AND in(priceList(prd), s)
;

edit (PriceListDetail d) + { edit(priceList(d)); }
EXTEND FORM managePrices
PROPERTIES (prd) NEWSESSION EDIT
;

DESIGN managePrices {
OBJECTS {
NEW pane {
fill = 1 ;
type = TABBED ;
NEW priceLists {
caption = '-' ;
MOVE BOX (p);
MOVE BOX (d);
}
NEW prices {
caption = '' ;
fill = 1 ;
type = SPLITH ;
NEW leftPane {
MOVE BOX (dt);
MOVE BOX ( TREE groups);
MOVE BOX (s);
}
NEW rightPane {
fill = 3 ;
type = SPLITV ;
MOVE BOX (pr) { fill = 3 ; }
MOVE BOX (prd);
}
}
}
}
}

NAVIGATOR {
NEW managePrices;
}

Source: https://habr.com/ru/post/id468553/


All Articles