Satınalma Talepleri düzeltme
This commit is contained in:
parent
8a3a00ae62
commit
6db67e121d
108 changed files with 18385 additions and 3168 deletions
38
.github/instructions/ai.instructions.md
vendored
38
.github/instructions/ai.instructions.md
vendored
|
|
@ -53,26 +53,28 @@ System nature:
|
|||
3. Every proposal must include tenant and permission design.
|
||||
4. Never bypass platform authorization patterns.
|
||||
5. Never hardcode secrets, tenant ids, or connection strings.
|
||||
6. **Stay inside the framework; ask before stepping out.** The platform may extend itself through
|
||||
its own mechanisms (seed artifacts; adding a missing event, prop, or small backward-compatible
|
||||
capability to an existing UI component — when Developer Kit tooling builds ~70% of the
|
||||
requested component, the rest is completed with such small additions, never with a new
|
||||
component; backward-compatible additions to script recipes / editor options / tokens).
|
||||
Anything beyond that — a new React component or page, a new toolbox family, core engine changes (ListForm
|
||||
runtime, seeders, code generator, auth, DataSourceManager, dispatcher/compiler), new ABP
|
||||
entity/module/migration, platform table schema changes, new NuGet/npm dependencies, the
|
||||
`App.Menus.Routes.json` seed data (except the `Seo*` columns of an existing row, which are part
|
||||
of ordinary production — lowcode §0.9), new external integrations — is **out of frame**: finish everything that
|
||||
fits inside the frame first, then ask the user with a single question (why configuration is
|
||||
insufficient, the smallest change that works, files touched, rollback) and proceed **only with
|
||||
explicit approval**. Approval is per request and does not carry over. Full lists:
|
||||
6. **No new Core feature without the command.** Core = all source code under `api/` and `ui/`;
|
||||
the frame = artifacts generated under `configs/seeds/` (wizard, SQL objects, `crud/`, custom
|
||||
components, Custom Endpoints, Dynamic Services, workers, notifications, language/permission
|
||||
rows, SEO, module docs). A new Core feature — however small or backward compatible: a DTO
|
||||
field, a prop/event on an existing UI component, a script recipe, an editor option key, a
|
||||
default-value token, a new React component/page, engine/seeder/MCP changes, new entity/
|
||||
migration, platform table schema, NuGet/npm packages, `App.Menus.Routes.json` rows (except the
|
||||
`Seo*` columns of an existing row — lowcode §0.9), external integrations — is written **only
|
||||
when the user gives the command "core sisteme ekle"** (or an equivalent that names the Core
|
||||
change). Before concluding Core is needed, scan the full ListForm capability inventory
|
||||
(`lowcode-reference.instructions.md` §0–§9, lowcode §4–§9). Without the command: finish what
|
||||
fits in the frame and end with a single "Core gerektiren kısım" note (missing capability, why
|
||||
the inventory falls short, smallest change, files, rollback) — do not offer Core as an
|
||||
option to pick. Bug fixes that restore documented behaviour without new settings are not new
|
||||
features. The command covers only the named change and does not carry over. Full lists:
|
||||
`lowcode.instructions.md` §0.8.
|
||||
|
||||
Exception policy:
|
||||
|
||||
- Code-level React or backend development can be considered only if user explicitly requests code implementation and configuration path is insufficient.
|
||||
- If exception is required, AI must explain why configuration-based options are not enough.
|
||||
- Never say "cannot be done": the answer is either an in-frame build or an approval question.
|
||||
- Code-level React or backend development happens only on the user's explicit command ("core sisteme ekle" or a request naming the code change).
|
||||
- When Core would be needed, explain in a sentence or two why the configuration inventory is not enough.
|
||||
- Never say "cannot be done": the answer is an in-frame build plus, if needed, a "Core gerektiren kısım" note.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -461,8 +463,8 @@ When configuration cannot satisfy requirement:
|
|||
1. Try SQL-based design
|
||||
2. Try Custom Endpoint
|
||||
3. Try Dynamic Service
|
||||
4. Propose minimal code change with explicit justification — this step is out of frame:
|
||||
**ask and wait for approval before touching code** (rule 3.6).
|
||||
4. Describe the minimal code change with explicit justification — this step is Core:
|
||||
**do not touch code until the user says "core sisteme ekle"** (rule 3.6).
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,9 @@ sorusunda buraya bak.
|
|||
`ColumnFormatDto` (alan) `*Json` kolonlarının ham metnini `[JsonIgnore]` ile gizler ve istemciye
|
||||
yalnızca tipli DTO'ya (`SchedulerOptionJson` → `SchedulerOptionDto`) çözülmüş hâlini yollar.
|
||||
Dolayısıyla:
|
||||
- DTO'da olmayan bir DevExtreme seçeneğini `*Json`'a yazmak **işe yaramaz**; kalıcı olarak
|
||||
gerekiyorsa önce ilgili DTO'ya alan eklenir (ve bu dosya güncellenir).
|
||||
- DTO'da olmayan bir DevExtreme seçeneğini `*Json`'a yazmak **işe yaramaz**; DTO'ya alan
|
||||
eklemek Core'dur ve yalnızca "core sisteme ekle" komutuyla yapılır (`lowcode` §0.8); eklenince
|
||||
bu dosya da güncellenir.
|
||||
- Çözme `JsonSerializer`'ın varsayılan ayarlarıyla yapılır: anahtarlar **PascalCase ve
|
||||
büyük/küçük harfe duyarlıdır**. `"visible"` yazılan yerde `"Visible"` beklenir; küçük harfli
|
||||
anahtar hata vermez, sessizce düşer. İstemcinin gördüğü camelCase hâl API çıktısıdır, seed'e
|
||||
|
|
@ -64,7 +65,7 @@ ama hiçbirini görmeden bırakma; kullanıcı "şunu da yapabilir miydik?" dedi
|
|||
| 10 | **Özet** | Toplam/adet satırı, grup özetleri, pivot | §9.5 · §6 |
|
||||
| 11 | **Biçimlendirme** | Koşullu satır/hücre rengi, CSS sınıfı | `lowcode` §4.3.7 |
|
||||
| 12 | **Düzenleme deneyimi** | Popup/satır/hücre/batch, form grupları, kopyalama, toplu silme | §3 |
|
||||
| 13 | **Aksiyonlar** | Toolbar ve satır butonları: adres, diyalog, script, yetki, koşullu görünürlük | `lowcode` §4.9 |
|
||||
| 13 | **Aksiyonlar** | Hazır toolbar/satır butonları, URL parametreleri, not/ek/geçmiş, içe-dışa aktarma; özel butonlar: adres, diyalog, script, yetki, koşullu görünürlük | §5.8 · `lowcode` §4.9 |
|
||||
| 14 | **Yazma mantığı** | Özel SQL, before/after kancaları, farklı servis adresi | §4 |
|
||||
| 15 | **Ana-detay** | Alt form sekmeleri ve ilişki alanları | §5.2 |
|
||||
| 16 | **Gösterge** | Üstte KPI kartları, grafik | §5.3 · §8 |
|
||||
|
|
@ -105,10 +106,10 @@ ve çoğu isteğin cevabı aslında oradadır:
|
|||
| `SelectCommand` | — | Tablo/view adı, fonksiyon çağrısı ya da sorgu metni |
|
||||
| `TableName` | `SelectCommand` | Üretilen `SELECT`'te kolonların ve join'lerin önüne yazılan **alias**. Boşsa `SelectCommand` kullanılır. `4` Query'de **zorunludur**: sorgu `FROM (…) AS "{TableName}"` biçiminde türetilmiş tablo olarak sarılır ve boş bırakılırsa sorgu metni alias olur (SQL hatası). Wizard/MCP `deploy_wizard` Query ekranına `"Q"` (`WizardConsts.QuerySourceAlias`) yazar; fonksiyon çağrısında da kısa bir ad yaz |
|
||||
| `KeyFieldName` · `KeyFieldDbSourceType` | — · `16` String | Anahtar kolon ve `System.Data.DbType` karşılığı. `4` Query'de ikisi de **zorunludur** (kolonlar katalogdan okunamaz); wizard/`deploy_wizard` anahtarsız Query ekranını reddeder, tip boşsa (`0`) seçilen alanlardaki karşılığından tamamlar. Ana tablo (en dıştaki `FROM`) `IsDeleted` taşıyorsa `DefaultFilter` yazılır ve sorgu `IsDeleted`'i seçmek zorundadır |
|
||||
| `SelectFieldsDefaultValueJson` | — | **Okuma** sorgusuna parametre olarak katılan değerler (`FieldsDefaultValueDto[]`) — `@USERID`, `@TENANTID` gibi |
|
||||
| `SelectFieldsDefaultValueJson` | — | ListForm editöründe (Veritabanı › Select) düzenlenir ama runtime **okumaz** (`DefaultValueManager` Select'te `FormFieldsDefaultValueJson`'ı kullanır). Okuma koşulu `DefaultFilter`'a token'la yazılır (`lowcode` §4.3.5) |
|
||||
| `DefaultFilter` | — | Her sorgunun sonuna `AND` ile eklenen sabit `WHERE` koşulu. `DefaultValueHelper` üzerinden geçer, yani `@USERID`/`@TENANTID`/`@NOW` gibi token'lar çözülür. Soft delete'li tabloda (`IsDeletedField: true`) wizard buraya `"IsDeleted" = 'false'` yazar |
|
||||
| `SortMode` | — | **Metin**: `"single"` \| `"multiple"` \| `"none"` (`PlatformConsts.GridOptions.SortMode*`; wizard `single` yazar) |
|
||||
| `PageSize` | — | Sayfa başına kayıt; `0` = tümü |
|
||||
| `PageSize` | `50` (DB) | Sayfa başına kayıt; `0` = tümü. C# varsayılanı `0`, veritabanı varsayılanı `50`; boşsa grid `20` kullanır |
|
||||
| `Name` · `Title` · `Description` | — | Ekran adı, başlığı, açıklaması — **dil anahtarı** yazılır |
|
||||
| `IsTenant` · `IsBranch` · `IsOrganizationUnit` | `IsMultiTenant` · `false` · `false` | Otomatik kırılım filtresi; `IsTenant` ayrıca bağlantı çözümünü belirler (`lowcode` §9.3.3) |
|
||||
| `SeedFilePath` · `SeedSyncInsert` · `SeedSyncUpdate` · `SeedSyncDelete` | — · `false` | Ekranın verisini `data/` altındaki dosyaya aynalar; `.json` uzantılı değer tek dosya, uzantısız değer klasör (`lowcode` §9.15) |
|
||||
|
|
@ -136,10 +137,11 @@ ve çoğu isteğin cevabı aslında oradadır:
|
|||
| `PivotOptionJson` | Pivot görünümü | §6 |
|
||||
| `TreeOptionJson` · `GanttOptionJson` · `SchedulerOptionJson` · `TodoOptionJson` | Ağaç/Gantt/Takvim/Kanban eşlemeleri | §7 |
|
||||
| `SeriesJson`, `CommonJson` ve diğer 19 grafik kolonu | Chart görünümü (21 kolon; `DataSourceJson` okunmaz) | §8 |
|
||||
| `ExportJson` | Grafik dışında **Grid/Pivot dışa aktarmayı da** açar: `Enabled` + `AllowExportSelectedData`; Grid yalnız `pdf`/`xlsx`, Pivot yalnız `xlsx`. Grid düğmesi ayrıca `PermissionJson.E` ister | §8.4 · §5.8 |
|
||||
| `CustomJsSourcesJson` · `CustomStyleSourcesJson` | Sayfaya enjekte edilen JS/CSS | §5.5 |
|
||||
| `Width` · `Height` · `FullHeight` | Ekran boyutu. `Height > 0` sabit piksel yüksekliği verir. Grid/Tree/Gantt/Scheduler'da `FullHeight` bayrağı görünümü `calc(100vh - …)` ile sayfaya yayar; **TodoBoard** bayrağa bakmaz, `Height` verilmediyse panoyu her zaman sayfanın kalan yüksekliğine yayar (kolonlar kendi içinde kayar), alt form olarak açıldığında ise içeriği kadar yer kaplar. | — |
|
||||
| `ListFormType` · `IsSubForm` · `SubFormsListFormType` · `ShowNote` | Ekranın türü ve alt form davranışı | §5.6 |
|
||||
| `CultureName` · `UserId` · `RoleId` | Aynı ekranın dil/kullanıcı/rol varyantı | §5.7 |
|
||||
| `CultureName` · `UserId` · `RoleId` | Ekranın dil varyantı (`UserId`/`RoleId` okunmaz — alan seviyesinde çalışır) | §5.7 |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -182,18 +184,18 @@ Adı yalnızca sayfalamayı çağrıştırsa da bu blok **kaydırma ve yükleniy
|
|||
| --- | --- | --- |
|
||||
| `Visible` | `true` | Sayfalama şeridi |
|
||||
| `ShowPageSizeSelector` | `false` | Sayfa boyu seçici |
|
||||
| `ShowInfo` | `false` | "Page 1 of 4 (37 items)" bilgisi |
|
||||
| `ShowInfo` | `false` | "Page 1 of 4 (37 items)" bilgisi — **Grid okumaz** (sabit kapalı); Tree (boşsa `true`) ve Card okur |
|
||||
| `ShowNavigationButtons` | `true` | İleri/geri düğmeleri |
|
||||
| `AllowedPageSizes` | `"10,20,50,100"` | **Virgüllü metin**, dizi değil |
|
||||
| `InfoText` | `"Page {0} of {1} ({2} items)"` | `{0}` sayfa · `{1}` toplam sayfa · `{2}` kayıt |
|
||||
| `InfoText` | `"Page {0} of {1} ({2} items)"` | `{0}` sayfa · `{1}` toplam sayfa · `{2}` kayıt — yalnız Tree ve Card |
|
||||
| `DisplayMode` | `"adaptive"` | `adaptive` \| `compact` \| `full` |
|
||||
| `ScrollingMode` | `"standard"` | `standard` \| `virtual` \| `infinite` — uzun listelerde `virtual` |
|
||||
| `LoadPanelEnabled` | `"auto"` | **Metin** alanıdır: `"auto"` \| `"true"` \| `"false"` |
|
||||
| `LoadPanelEnabled` | `"auto"` | **Metin** alanıdır: `"auto"` \| `"true"` \| `"false"`. İstemci metni boolean'a çevirir (`resolveLoadPanelEnabled`); Grid, Tree, Pivot ve Card aynı kuralı kullanır |
|
||||
| `LoadPanelText` | `"Loading..."` | Yükleniyor metni |
|
||||
|
||||
Sayfa başına kayıt sayısı ekranın `PageSize` alanındadır; `0` = tümü. `ScrollingMode` ile
|
||||
`PageSize` birlikte düşünülür: `virtual`/`infinite` seçilip `PageSize: 0` yazılırsa sayfalama
|
||||
devre dışı kalır ve tüm küme tek istekte çekilir.
|
||||
devre dışı kalır ve tüm küme tek istekte çekilir. `ScrollingMode` ve `LoadPanel*` Pivot'ta da okunur.
|
||||
|
||||
### 2.4 `SelectionJson` (`SelectionDto`)
|
||||
|
||||
|
|
@ -205,19 +207,25 @@ devre dışı kalır ve tüm küme tek istekte çekilir.
|
|||
| `ShowCheckBoxesMode` | `"always"` | `always` \| `none` \| `onClick` \| `onLongTap` |
|
||||
|
||||
Toolbar butonları seçili satırlarla çalışır (`lowcode` §4.9); onay akışı varsa wizard `single` yazar.
|
||||
Tree yalnız `Mode`'u okur (`recursive` `TreeOptionJson.RecursiveSelection`'dan gelir); `AllowSelectAll`,
|
||||
`SelectAllMode`, `ShowCheckBoxesMode` Grid ve Card'da çalışır, `AllowSelectAll` Pivot'un başlık filtresinde
|
||||
"tümünü seç"i de açar. `SubFormsListFormType: "List"` ekranında alt form sekmeleri seçili satırla
|
||||
beslendiği için `Mode` `single`/`multiple` olmalıdır (§5.6).
|
||||
|
||||
### 2.5 `StateStoringJson` (`StateStoringDto`)
|
||||
|
||||
| Anahtar | Varsayılan | Anlam |
|
||||
| --- | --- | --- |
|
||||
| `Enabled` | `true` | Kullanıcının kolon/filtre/sıralama tercihleri saklansın mı |
|
||||
| `Type` | `"custom"` | `custom` (sunucuda kullanıcı bazlı) \| `localStorage` \| `sessionStorage` |
|
||||
| `Enabled` | `true` | Toolbar'daki **Grid durumunu kaydet / sıfırla** menüsünü açar. Kayıt **elle** yapılır (Grid/Tree/Pivot'ta otomatik kayıt kapalı); kayıtlı durum `Enabled`'dan bağımsız her açılışta yüklenir. Pivot'un kaydet/sıfırla düğmeleri her zaman görünür |
|
||||
| `Type` | `"custom"` | **Okunmaz** — durum her zaman sunucuya (`ListFormCustomization`) yazılır; editör de yalnız `custom` sunar |
|
||||
| `StorageKey` | — | Anahtar; boşsa sunucu `listFormGridStorage-{ListFormCode}` üretir |
|
||||
| `SavingTimeout` | `5000` | Değişiklikten kaç ms sonra yazılacağı — **`[Range(1500, 5000)]`**, dışına çıkan değer doğrulamada reddedilir |
|
||||
| `SavingTimeout` | `5000` | Yalnız **TodoBoard**'da otomatik kayıt bekleme süresi — **`[Range(1500, 5000)]`**, dışına çıkan değer doğrulamada reddedilir |
|
||||
|
||||
`Type: "custom"` tercih edilir: tercih sunucuda `ListFormCustomization` kaydı olarak
|
||||
(`ListFormCustomizationTypeEnum.GridState = 2`) kullanıcı bazlı saklanır, bu yüzden başka
|
||||
tarayıcıdan girildiğinde de korunur. `localStorage`/`sessionStorage` yalnızca o tarayıcıdadır.
|
||||
Durum sunucuda `ListFormCustomization` kaydı olarak (`ListFormCustomizationTypeEnum.GridState = 2`)
|
||||
saklanır, başka tarayıcıdan girildiğinde de korunur. Kayıt **kullanıcı > rol > genel** önceliğiyle
|
||||
çözülür: `UserId`/`RoleId` boş `GridState` herkese, `RoleId` dolu olan o role varsayılan düzen verir —
|
||||
`UserUiFilter` (paylaşılan kayıtlı filtre) için de aynısı geçerlidir. Seçili görünüm (grid/card/…) ve
|
||||
Card'ın kart başına kolon sayısı ise sunucuda değil **tarayıcının localStorage**'ındadır.
|
||||
Aynı `GridState` kaydı görünüm başına ayrı `FilterName` taşır: `list-`, `tree-`, `pivot-`, `todo-`,
|
||||
`gantt-` ve form sayfası için `form-{StorageKey}` (`useListFormStateStoring`). Form sayfasının state'i
|
||||
kullanıcının **alan sırasıdır** (`{"fieldOrder": {"Alan": 1, …}}`, grup içi sıra): araç çubuğundaki
|
||||
|
|
@ -243,15 +251,19 @@ ekranın alanlarından, toplam türü `sum avg min max count`'tan seçilir. "Tü
|
|||
|
||||
**`FilterRowJson`** (`GridFilterRowDto`): `Visible` (`false`), `ApplyFilter` (`auto` \| `onClick`),
|
||||
`AllowUserUiFilterSave` (varsayılan `true` — kullanıcı kendi filtresini kaydedebilir;
|
||||
kayıt `ListFormCustomizationTypeEnum.UserUiFilter = 1` olarak tutulur).
|
||||
kayıt `ListFormCustomizationTypeEnum.UserUiFilter = 1` olarak tutulur). `AllowUserUiFilterSave` aynı zamanda
|
||||
toolbar'daki **Rapor › Liste** düğmesini ve kayıtlı filtre seçim kutusunu açar; `ApplyFilter: onClick`
|
||||
filtre satırına **Filtre uygula** düğmesi ekler. Filtre uygulanınca başlık paneli renkli kenarlık alır
|
||||
(kayıtlı durum varsa farklı renk).
|
||||
|
||||
**`HeaderFilterJson`** (`GridHeaderFilterDto`): `Visible` (`false`), `AllowSearch` (`false`),
|
||||
`Height` (`325`), `Width` (`252`), `SearchTimeout` (`500`).
|
||||
`Height` (`325`), `Width` (`252`), `SearchTimeout` (`500`). Grid, Tree ve Gantt yalnız `Visible`'ı okur
|
||||
(arama kolon bazında `ColumnHeaderJson.AllowSearch`'tedir); diğer dört anahtar yalnız Card ve Pivot'ta çalışır.
|
||||
|
||||
**`FilterPanelJson`** (`FilterPanelDto`): `Visible` (`false`), `FilterEnabled` (`false`),
|
||||
`Texts.ClearFilter` (`"Clear"`) / `Texts.CreateFilter` (`"Create Filter"`) /
|
||||
`Texts.FilterEnabledHint` (`"Enable the filter"`), `CustomizeText` (serbest JSON; filtre
|
||||
metnini biçimlendirmek için — sözlükte tipi yoktur, olduğu gibi bileşene geçer).
|
||||
`Texts.FilterEnabledHint` (`"Enable the filter"`), `CustomizeText`. Grid ve Tree yalnız `Visible`'ı okur;
|
||||
`Texts` yalnız Card'da çalışır; `FilterEnabled` ve `CustomizeText` **hiçbir görünümde okunmaz**.
|
||||
|
||||
**`SearchPanelJson`** (`SearchPanelDto`): `Visible` (`false`), `Width` (`160`).
|
||||
|
||||
|
|
@ -268,17 +280,17 @@ metnini biçimlendirmek için — sözlükte tipi yoktur, olduğu gibi bileşene
|
|||
| --- | --- | --- |
|
||||
| `Mode` | `"popup"` | `batch` \| `cell` \| `row` \| `form` \| `popup` |
|
||||
| `RefreshMode` | `"full"` | `full` \| `reshape` \| `repaint` |
|
||||
| `AllowAdding` / `AllowUpdating` / `AllowDeleting` | `false` | Aksiyon izinleri (yetki ayrıca `PermissionJson`) |
|
||||
| `AllowAllDeleting` | `false` | Toplu silme düğmesi |
|
||||
| `AllowDuplicate` | `false` | Kaydı kopyalayarak yeni kayıt |
|
||||
| `AllowDetail` | `false` | Satırda Detay düğmesi |
|
||||
| `AllowAdding` / `AllowUpdating` / `AllowDeleting` | `false` | Aksiyon izinleri (yetki ayrıca `PermissionJson`: Ekle `C`, Düzenle `U`, Sil `D`). `AllowDeleting` + `D` toolbar'a **Seçilileri sil** düğmesi de ekler (2+ satır seçiliyken görünür). `Mode: batch` + `AllowUpdating` + `U` toolbar'a Kaydet/Geri al getirir |
|
||||
| `AllowAllDeleting` | `false` | **Tümünü sil (filtreli)** düğmesi: filtredeki bütün kayıtları, önce sayıyı gösterip onayla siler; `AllowDeleting` + `D` de gerekir |
|
||||
| `AllowDuplicate` | `false` | Satırda **Kopyala**: onay sorar, `list-form-data/duplicate` (`InsertCommand` + kancalar + `InsertFieldsDefaultValueJson`). Düğme **`C`** (Create) yetkisi ister |
|
||||
| `AllowDetail` | `false` | Satırda Detay düğmesi — `/admin/form/{kod}/{id}` yeni sekmede; **`U`** yetkisi ister (`R` değil) |
|
||||
| `OpenDetailAfterInsert` | `false` | Popup'tan eklenen kayıt kaydedilince aynı sekmede kaydın form sayfasına (`/admin/form/{ListFormCode}/{Id}`) geçilir. Grid, Tree, Card ve Scheduler'da çalışır; anahtar insert yanıtından alınır, dönmezse geçilmez. Wizard cevabında da aynı adla vardır (`ListFormWizardDto.OpenDetailAfterInsert`); ne zaman açılacağı `lowcode` §4.2 Davranış tablosunda |
|
||||
| `ConfirmDelete` | `true` | Silme onayı |
|
||||
| `UseIcons` | `false` | Aksiyonlar ikon olarak |
|
||||
| `NewRowPosition` | `"viewportTop"` | `first` \| `last` \| `pageTop` \| `pageBottom` \| `viewportTop` \| `viewportBottom` |
|
||||
| `StartEditAction` | `"click"` | `click` \| `dblClick` |
|
||||
| `SelectTextOnEditStart` | `false` | Düzenlemeye girince metni seç |
|
||||
| `EditColumnName` | — | Aksiyon sütununun başlığı |
|
||||
| `EditColumnName` | — | **Ölü ayar** — editörde var ama komut sütununa başlık verilmez |
|
||||
| `SendOnlyChangedFormValuesUpdate` | `false` | Update'te yalnızca değişen alanları gönder |
|
||||
| `AddPageUrl` | — | Yeni kayıt popup yerine bu adreste açılır (`window.open`; PWA'da aynı sekme) |
|
||||
| `AddDialogName` | — | Yeni kayıt kayıtlı bir diyalogda açılır (`CommandColumnDto.DialogName` ile aynı liste). `AddPageUrl` ile birlikte verilirse **diyalog önceliklidir**; diyalog kapanınca liste yenilenir |
|
||||
|
|
@ -290,6 +302,12 @@ metnini biçimlendirmek için — sözlükte tipi yoktur, olduğu gibi bileşene
|
|||
`DragEnabled` (`true`), `RestorePosition` (`true`),
|
||||
`Position` (`center` \| `top` \| `bottom` \| `left` \| `right`).
|
||||
|
||||
- `Title` dil anahtarıdır (`::` eklenip çevrilir; önüne ✚/🖊️ konur).
|
||||
- `Height` sabit yükseklik değil **azami yüksekliktir** (`maxHeight`; boşsa `90vh`), popup içeriğe göre büyür.
|
||||
- Mobilde (`<768px`, `pointer:coarse` ya da `hover:none`) popup tam genişlik/tam ekran açılır, form tek
|
||||
kolona iner; tam ekran aç/kapa düğmesi her zaman vardır.
|
||||
- `DragEnabled`, `RestorePosition`, `Position` çalışır ama ListForm editöründe alanı yoktur — seed ile yazılır.
|
||||
|
||||
### 3.2 `EditingFormJson` (`EditingFormDto[]`)
|
||||
|
||||
Düzenleme formundaki grupların listesi. Alanların hangi gruba düştüğü `ListFormField` üzerindeki
|
||||
|
|
@ -321,18 +339,48 @@ olanlar dışarıda kalır.
|
|||
|
||||
**Kancalar, kod yazmadan iş mantığı çalıştırmanın yeridir**: stok düşme, hareket kaydı, durum
|
||||
güncelleme, log, bildirim kuyruğuna satır ekleme. Karmaşıklaşınca gövdeyi bir stored procedure'e
|
||||
taşı ve kancadan onu çağır (`EXEC Wms_S_AfterOrderInsert @Id, @USERID`).
|
||||
taşı ve kancadan onu çağır (`EXEC Wms_S_AfterOrderInsert @Id, @LastModifierId`).
|
||||
|
||||
- Kancalar ana komutla **aynı parametre sözlüğünü** kullanır.
|
||||
- Insert'in ana komutu `ExecuteScalar` ile çalışır (SQL Server `OUTPUT Inserted.{Key}`, PG `RETURNING`);
|
||||
özel `InsertCommand` anahtarı döndürmezse istemci yeni kaydın anahtarını alamaz (detaya gitme, alt form).
|
||||
- Otomatik Update'te istekte `TenantId` varsa `WHERE`'e `AND TenantId` eklenir; otomatik Delete'te
|
||||
**bütün parametreler** `WHERE` koşuludur.
|
||||
- **Kopyala** (`list-form-data/duplicate`) `InsertCommand` + Insert kancaları + `InsertFieldsDefaultValueJson`
|
||||
ile çalışır.
|
||||
- Yazmadan sonra ekranın seed senkronu çalışır (`SeedSync*`, `lowcode` §9.15).
|
||||
|
||||
### 4.2 Komut içinde kullanılabilen anahtarlar
|
||||
|
||||
| Token | Değer |
|
||||
| --- | --- |
|
||||
| `@ID` | Kaydın anahtarı (Delete'te seçili anahtar kümesi) |
|
||||
| `@USERID` · `@USERNAME` · `@ROLES` | Oturumdaki kullanıcı |
|
||||
| `@FieldName` | Ekrandan gelen o alanın değeri — tablodaki her kolon için geçerlidir (`@OrderNo`, `@Amount`) |
|
||||
Yazma komutlarında ve kancalarında **metin değiştirme yoktur** (`DefaultValueHelper` çalışmaz); yalnızca
|
||||
Dapper parametreleri bağlanır:
|
||||
|
||||
`*FieldsDefaultValueJson` ile üretilen değerler (`@NOW`, `@NEWID`, `@TENANTID`, Sequence…)
|
||||
komuta parametre olarak katılır (`lowcode` §4.3.5). **String birleştirme ile sorgu kurma.**
|
||||
| Parametre | Kaynağı |
|
||||
| --- | --- |
|
||||
| `@{FieldName}` | İstekte gelen alan — Insert/Update'te yalnızca alan seviyesinde `C`/`U` yetkisi olanlar (Delete'te yetki süzgeci yok) |
|
||||
| `@{FieldName}` | `*FieldsDefaultValueJson` öğesi — adı token değil **alan adıdır**: `@CreatorId`, `@CreationTime` (`@USERID` değil) |
|
||||
| `@TenantId` | `IsTenant` açıksa |
|
||||
| `@{KeyFieldName}` | Yalnızca **otomatik üretilen** Update/Delete'te eklenir. Özel `UpdateCommand`/`DeleteCommand`'da anahtar parametresi gelmez; wizard bunu `DeleteFieldsDefaultValueJson`'a `{FieldName:"Id", Value:"@ID", CustomValueType:2}` yazarak çözer (`DefaultDeleteCommand` → `… WHERE "Id" IN @Id`) |
|
||||
|
||||
Bu yüzden `@USERID`, `@USERNAME`, `@ROLES`, `@ID` komut metninde **çalışmaz** ("Must declare scalar
|
||||
variable"); kullanıcıya/zamana bağlı değer gerekiyorsa önce ilgili `*FieldsDefaultValueJson`'a alan adıyla
|
||||
yazılır (`{FieldName:"LastModifierId", Value:"@USERID", CustomValueType:2}`), komutta `@LastModifierId`
|
||||
kullanılır (`lowcode` §4.3.5). **String birleştirme ile sorgu kurma.**
|
||||
|
||||
**Metin değiştirmenin çalıştığı yerler** (`DefaultValueHelper.GetDefaultValue`; `@USERID`, `@USERNAME`,
|
||||
`@ROLES`, `@DATE`, `@NOW`, `@DAY`, `@MONTH`, `@YEAR`, `@TENANTID`): `SelectCommand`, `DefaultFilter`,
|
||||
kullanıcı `ServerWhere` özelleştirmesi, widget `SqlQuery`, `LookupQuery`, `DbQuery` varsayılanının
|
||||
`SqlQuery`'si, Custom Endpoint parametre varsayılanları, rapor lookup'ları. Host bağlamında
|
||||
`= '@TENANTID'` → `IS NULL`, yalın `@TENANTID` → `NULL` olur; `@ROLES` `','` ile birleşir
|
||||
(`IN ('@ROLES')` kalıbı). `@ID`, `@NEWID`, `@SELECTED_IDS`, `@AUTONUMBER` metinde çözülmez;
|
||||
`@BRANCHID`/`@LANG` diye token yoktur. Çalışmadığı yerler: yazma komutları ve kancaları, `ServerJoin`
|
||||
özelleştirmesi, `ExtraFilterJson` (istemci filtresi olarak parametreleşir), grafik özet sorgusu.
|
||||
|
||||
**Örtük filtreler** (token değil, sorguya kendiliğinden eklenir): `IsTenant` → `TenantId = '{id}'`/`IS NULL`;
|
||||
`IsBranch` → `BranchId IN (kullanıcının şubeleri)` — kullanıcının şubesi yoksa hiç satır gelmez;
|
||||
`IsOrganizationUnit` → `OrganizationUnitId IN (birim + alt birimler)`; `ApprovalIsFilterUserName` →
|
||||
onaycı filtresi. Widget SQL'i bu filtrelerden **geçmez** (kiracı koşulunu kendisi yazar). Yazma tarafında
|
||||
şube/birim ataması yoktur — `BranchId` varsayılanla ya da formdan gelir.
|
||||
|
||||
### 4.3 `*ServiceAddress`
|
||||
|
||||
|
|
@ -341,6 +389,17 @@ komuta parametre olarak katılır (`lowcode` §4.3.5). **String birleştirme ile
|
|||
Service'e devretmek istiyorsan bu alanı o ucun adresiyle değiştirirsin — ekranın geri kalanı
|
||||
(form, doğrulama, yetki) aynı kalır.
|
||||
|
||||
- Çağrı **her zaman POST**'tur ve adres `'/api/app/' + adres` olarak kurulur (baştaki `/` silinir);
|
||||
`http…` ile başlayan mutlak adres de önek alır ve çalışmaz — dış servis bir Custom Endpoint / Dynamic
|
||||
Service arkasına konur.
|
||||
- Gövdeler: insert `{data, listFormCode}` · update `{keys:[key], data, listFormCode}` (yalnızca değişen
|
||||
alanlar) · delete `{keys:[key], listFormCode}`.
|
||||
- **Adres boşsa işlem sessizce yapılmaz**; TodoBoard ekle/güncelle/sil düğmeleri kapanır,
|
||||
`UpdateServiceAddress` boşsa iş akışı toolbar'ı tamamen gizlenir. Salt okunur ekran için adresleri
|
||||
boşaltmak yerine `EditingOptionJson`'daki izin bayraklarını kapat.
|
||||
- Yetki ucun kendisinde (Create/Update/Delete) denetlenir; bağlantı `DataSourceManager.GetDataSourceAsync(IsTenant,
|
||||
DataSourceCode)` ile çözülür (`DataSourceType` `1` Mssql · `2` Postgresql).
|
||||
|
||||
**Çok değerli alanlar bu iki yolda farklı davranır.** Varsayılan uçta payload bir sözlüktür
|
||||
(`data: {...}`) ve `dxTagBox` dizisini `QueryHelper.GetFormattedValue` `|` ile birleştirir.
|
||||
Tipli bir DTO alan uçta (`list-form-dynamic-api/...` gibi) böyle bir adım yoktur: dizi `string`
|
||||
|
|
@ -373,8 +432,8 @@ Alan seviyesindeki karşılığı `ListFormField.PermissionJson`'dır ve **şema
|
|||
| --- | --- | --- |
|
||||
| `Deny` | bool | `true` ise alan **hiç dönmez**; diğer anahtarlara bakılmaz |
|
||||
| `C` · `R` · `U` | string | Yaratma / okuma / güncelleme yetkisinin **adı**. Boşsa ekranın kendi Create/Read/Update yetkisi kullanılır |
|
||||
| `E` | bool | Alan dışa aktarımda yer alsın mı |
|
||||
| `I` | bool | Alan içe aktarımda kabul edilsin mi |
|
||||
| `E` | bool | Alan dışa aktarımda yer alsın mı — **yazılmazsa `false`**: `PermissionJson`'ı olmayan alan dışa aktarılmaz |
|
||||
| `I` | bool | Yalnızca istemcide: içe aktarma şablonunun kolonlarını seçer; sunucu yok sayar |
|
||||
|
||||
```json
|
||||
{ "C": "App.Mrp.Orders.Create", "R": "App.Mrp.Orders", "U": "App.Mrp.Orders.Update",
|
||||
|
|
@ -385,7 +444,8 @@ Alan seviyesindeki karşılığı `ListFormField.PermissionJson`'dır ve **şema
|
|||
**veritabanında yoktur** (`[NotMapped]`); `ListFormFieldManager.SetPermissionsAsync` bu
|
||||
JSON'u oturumdaki yetkilerle karşılaştırarak istek başına hesaplar. Üçü de `false` çıkan alan
|
||||
metadata'dan tamamen düşer — yani okuma yetkisi olmayan bir kolon sorguya bile girmez.
|
||||
Wizard varsayılan olarak `DefaultFieldPermissionJson(permissionName)` üretir.
|
||||
`C`/`U` yetkisi olmayan alan sunucuda insert/update verisinden atılır ve formda **salt okunur**
|
||||
görünür. Wizard varsayılan olarak `DefaultFieldPermissionJson(permissionName)` üretir.
|
||||
|
||||
### 5.2 `SubFormsJson` (`SubFormDto[]`)
|
||||
|
||||
|
|
@ -394,12 +454,18 @@ Wizard varsayılan olarak `DefaultFieldPermissionJson(permissionName)` üretir.
|
|||
| `TabType` | Sekmenin görünümü — `ListFormTabTypeEnum`: `List` \| `Card` \| `Tree` \| `Gantt` \| `Scheduler` \| `Todo` \| `Form` \| `Chart` \| `Pivot`. `Form` ana kayda bağlı **tek** kaydı gösterir: kayıt yokken "Yeni" düğmesi (hedef ekranda `AllowAdding` açıksa), kayıt varken yalnızca düzenleme; ikinci kayıt açılmaz |
|
||||
| `TabTitle` | Dil anahtarı |
|
||||
| `Code` | Hedef `ListFormCode` |
|
||||
| `IsRefresh` | Ana kayıt değişince yenilensin. MCP `deploy_wizard` yeni alt form bağlantısını `false` yazar; var olan bağlantıda önceki değer korunur |
|
||||
| `Relation[]` | `ParentFieldName` → `ChildFieldName` + `DbType` (`System.Data.DbType`, **sayı**; bileşik anahtarda birden çok satır) |
|
||||
| `IsRefresh` | `true` ise alt sekmede satır eklenip/değiştirilip/silindiğinde **ana form kaydı** yeniden çekilir (ana kayıt değişince alt sekme zaten her zaman yenilenir) — alt satırlardan hesaplanan başlık toplamı için açılır. MCP `deploy_wizard` yeni alt form bağlantısını `false` yazar; var olan bağlantıda önceki değer korunur |
|
||||
| `Relation[]` | `ParentFieldName` → `ChildFieldName` + `DbType` (`System.Data.DbType`, **sayı**). İstemci yalnızca değeri dolu **ilk** satırı kullanır — bileşik anahtar desteklenmez |
|
||||
|
||||
Alt formun kendisi de bir ListForm'dur: `IsSubForm = true` olmalı ve genellikle `CreateMenu:
|
||||
false` ile menüsüz üretilir (`lowcode` §4.2). `TabType`, hedef ekranın `LayoutJson`'ında açık
|
||||
olan bir görünüm olmalıdır; kapalı bir görünüm sekmede boş çizilir.
|
||||
false` ile menüsüz üretilir (`lowcode` §4.2). `TabType` hedefin `LayoutJson` bayrağına bakmaz (Grid/Card/
|
||||
Pivot bayrak kapalı olsa da çizilir); Tree/Gantt/Scheduler/Todo hedefte ilgili `*Expr` alanlarını ister.
|
||||
|
||||
- **`Form` sekmesi** kaydı ilişkiyle (`ChildFieldName = ana alanın değeri`) yükler; düzenlemede anahtar
|
||||
yüklenen kayıttan okunur. Yeni kayıtta ilişki alanı ana kaydın değeriyle dolu ve kilitli açılır.
|
||||
- **`Chart` sekmesi** ana ekranın grafik tanımını kullanır ve ilişkiyle süzülmez.
|
||||
- Form sayfasında alt formlar görüntüle/düzenle modunda çizilir, yeni kayıtta çizilmez. Adres
|
||||
`#{AltFormKodu}` ile açılırsa o sekme seçilir; sekme değişince hash yazılır.
|
||||
|
||||
### 5.3 `WidgetsJson` (`WidgetEditDto[]`)
|
||||
|
||||
|
|
@ -408,8 +474,8 @@ Ekranın üstündeki KPI şeridi. **Sözleşmesi sezgisel değildir, dikkatle ok
|
|||
| Anahtar | Ne yazılır |
|
||||
| --- | --- |
|
||||
| `SqlQuery` | Kartları besleyen sorgu. **Zorunludur** — boş olan widget hiç çizilmez |
|
||||
| `Title` · `SubTitle` · `Value` · `Color` · `Icon` · `OnClick` | **Sorgu sonucundaki kolon adları** — sabit metin değil. Sunucu her satırda bu adlı kolonu okur; kolon yoksa boş string döner. `Title`/`SubTitle` kolonunun **değeri** ekranda dil anahtarı olarak çözülür (`WidgetGroup`, `::` öneki eklenerek); karşılığı olmayan metin aynen basılır, bu yüzden sorguya dil anahtarı yazılır |
|
||||
| `ColSpan` · `ColGap` · `ClassName` | Şeritteki yerleşim (widget başına, karta değil) |
|
||||
| `Title` · `SubTitle` · `Value` · `Color` · `Icon` · `OnClick` | **Sorgu sonucundaki kolon adları** — sabit metin değil. `OnClick` kolonunun **değeri JS olarak `eval` edilir** (adres değil): `'window.open(''/admin/list/X'')' AS Tikla`. Sunucu her satırda bu adlı kolonu okur; kolon yoksa boş string döner. `Title`/`SubTitle` kolonunun **değeri** ekranda dil anahtarı olarak çözülür (`WidgetGroup`, `::` öneki eklenerek); karşılığı olmayan metin aynen basılır, bu yüzden sorguya dil anahtarı yazılır |
|
||||
| `ColSpan` · `ColGap` · `ClassName` | Şeritteki yerleşim (widget başına, karta değil): `ColSpan` 12 kolonluk ızgarada kart genişliği (mobilde 6'ya zorlanır), `ColGap` Tailwind `gap-{ColGap}` eki (`3` önerilir; `16` = 4rem) |
|
||||
| `ValueClassName` | Değerin CSS sınıfı, varsayılan `text-3xl` |
|
||||
| `IsActive` | **Varsayılanı `false`'tur** — yazılmazsa sorgu hiç çalışmaz ve şerit boş kalır; her widget'a `true` yaz |
|
||||
|
||||
|
|
@ -447,7 +513,8 @@ Sorgu ekranın bağlantısında (`IsTenant` + `DataSourceCode` ile çözülen, `
|
|||
- Kartlar GridDto ile gelir; Grid, Tree, Card, Gantt ve Scheduler görünümünde Yenile düğmesi ve
|
||||
satır ekleme/güncelleme/silme kartları yeniden çeker (`useListFormWidgets`). Yalnızca widget
|
||||
listesi değişir, GridDto değiştirilmez — görünüm durumu (sayfa, seçim) korunur. Kart sorgusu
|
||||
ekranın filtresine bağlı olmadığı için filtre değişikliği kartları yenilemez.
|
||||
ekranın filtresine bağlı olmadığı için filtre değişikliği kartları yenilemez. Pivot'ta şerit çizilir
|
||||
ama yenilenmez.
|
||||
- Kart sorgusu alt form sekmesinde `Relation` ile süzülmez; bu yüzden alt form olarak üretilen
|
||||
ekrana widget yazılmaz (menüsüz ya da menülü). Menüsüz (`CreateMenu: false`) wizard'ın `Widgets`'ı
|
||||
deploy'da ayrıca düşürülür; ekran alt form olarak (`SubForms` sekmesi, `isSubForm`) açıldığında
|
||||
|
|
@ -469,6 +536,12 @@ değişir: UI wizard başlangıç değerleri (`Wizard.tsx`), `ListFormWizardDto`
|
|||
(§7); bayrak açık olsa bile alanlar boşsa istemci görünümü göstermez (`List.tsx` `isLayoutValid`)
|
||||
ve seeder o görünümün JSON'unu yazmaz. `DefaultLayout`, `true` olan bir görünümü göstermelidir.
|
||||
|
||||
- **`Grid` bayrağı ölüdür**: Grid düğmesi her zaman çizilir, kapatılamaz.
|
||||
- `Card` bayrağı yalnız düğmeyi gizler; `DefaultLayout: "card"` bayrak kapalıyken de açılır.
|
||||
- Düğme koşulu `isLayoutValid`'den gevşektir: Tree düğmesi yalnız `ParentIdExpr`, Gantt düğmesi
|
||||
`ParentIdExpr` + `TitleExpr` ister. Geçersiz `DefaultLayout` ya da kayıtlı görünüm `grid`'e düşer.
|
||||
- Kullanıcının seçtiği görünüm sunucuda değil tarayıcının localStorage'ında (`admin.lists.states`) durur.
|
||||
|
||||
### 5.5 `CustomJsSourcesJson` / `CustomStyleSourcesJson`
|
||||
|
||||
Her ikisi de **string dizisidir**. Bir eleman `http` ya da `/` ile başlıyorsa dosya olarak
|
||||
|
|
@ -479,6 +552,9 @@ sayfaya eklenir (`<script src>` / `<link rel=stylesheet>`); aksi hâlde içerik
|
|||
["/assets/custom/orders.js", "console.log('orders ekranı yüklendi')"]
|
||||
```
|
||||
|
||||
Kaynaklar Grid, Tree, Pivot, Gantt, Scheduler ve form sayfasında yüklenir; Card, TodoBoard ve
|
||||
Chart yüklemez. ListForm editöründe alanı yoktur, yalnız seed ile yazılır.
|
||||
|
||||
**Son çaredir.** Önce `EditorScript`, `EditorOptions`, `ColumnStylingJson` ve `CommandColumnJson`
|
||||
denenir. Buraya yazılan kod ekran her açıldığında çalışır ve hiçbir yerde denetlenmez.
|
||||
|
||||
|
|
@ -487,20 +563,92 @@ denenir. Buraya yazılan kod ekran her açıldığında çalışır ve hiçbir y
|
|||
| Kolon | Varsayılan | Anlam |
|
||||
| --- | --- | --- |
|
||||
| `ListFormType` | `"List"` | `ListFormTypeEnum`: `List` (ızgara) \| `Form` (tek kayıt) \| `Chart` (yalnız grafik). Route karşılıkları: `/admin/list/{kod}` · `/admin/form/{kod}[/{id}[/edit]]` · `/admin/chart/{kod}` |
|
||||
| `IsSubForm` | `false` | Ekran alt form olarak da kullanılıyor mu |
|
||||
| `SubFormsListFormType` | `"Form"` | Alt form olarak açıldığında hangi görünümle geleceği |
|
||||
| `IsSubForm` | `false` | Bilgi amaçlı — runtime okumaz; alt form davranışını sekmenin `isSubForm` prop'u belirler |
|
||||
| `SubFormsListFormType` | `"Form"` | **Bu ekranın kendi** `SubFormsJson` sekmelerinin nerede çizileceği: `List` → liste sayfasında grid/tree/card'ın altında, **seçili satıra bağlı** ana-detay (`SelectionJson.Mode` `single`/`multiple` olmalı) · `Form` → yalnız form/detay sayfasında |
|
||||
| `ShowNote` | `true` | Not paneli (alt form ya da iş akışı varsa wizard açar) |
|
||||
|
||||
`ListFormType = "Form"` listesiz, tek kayıtlık kart ekrandır; canlı örneği Administration ›
|
||||
Licence'tır (§12.7). `Pivot` bir `ListFormType` **değildir** — pivot, `LayoutJson.Pivot`
|
||||
Licence'tır (§12.7); `/admin/form/{kod}` (id'siz) adresinde yeni kayıt yerine görüntüleme açılır ve
|
||||
kaydı `DefaultFilter` seçer. ListForm editörü yalnız `List`/`Form` sunar (`Chart` seed ile yazılır).
|
||||
`Pivot` bir `ListFormType` **değildir** — pivot, `LayoutJson.Pivot`
|
||||
bayrağıyla açılan bir görünümdür ve `/admin/pivot/...` diye bir route yoktur.
|
||||
|
||||
### 5.7 Varyantlar
|
||||
|
||||
Aynı `ListFormCode` ile ikinci bir `ListForm` kaydı açılıp `CultureName`, `UserId` ya da `RoleId`
|
||||
doldurulursa o dil/kullanıcı/rol için **farklı sütun düzeni ve ayarlar** verilebilir. Aynı şey
|
||||
`ListFormField` ve `Menu` kayıtları için de geçerlidir. Wizard bunu üretmez; ihtiyaç varsa
|
||||
ListForm editöründen açılır ve seed karşılığı elle yazılır.
|
||||
- **`ListForm`**: yalnızca `CultureName` varyantı çalışır (`ListFormManager.GetUserListForm` kültürle
|
||||
süzer). `ListForm.UserId`/`RoleId` **hiçbir yerde okunmaz**; aynı kod ve kültürle ikinci satır açılırsa
|
||||
herkese rastgele biri döner — ekran düzeyinde kullanıcı/rol varyantı açma.
|
||||
- **`ListFormField`**: kullanıcı > rol > varsayılan; aktif UI kültürü > `DefaultLanguage` (`en`)
|
||||
(`ListFormFieldManager`). Kullanıcı/rol bazlı farklı sütun buradan verilir.
|
||||
- **Kullanıcı tercihi**: grid durumu, kayıtlı filtre ve `ServerWhere`/`ServerJoin` `ListFormCustomization`'da
|
||||
durur (lowcode §3 `ListFormCustomizationType`).
|
||||
- Kullanıcıya özel grafik serisi `ChartSeriesDto.UserId` ile verilir (§8.1).
|
||||
|
||||
Wizard varyant üretmez; ihtiyaç varsa ListForm editöründen açılır ve seed karşılığı elle yazılır.
|
||||
|
||||
### 5.8 Runtime'da hazır gelenler — toolbar, satır, URL, not, içe aktarma
|
||||
|
||||
Aşağıdakilerin hepsi ekranla **kendiliğinden** gelir; açmak için yalnızca gösterilen bayrak/yetki yazılır.
|
||||
"Bunun için kod gerekir" demeden önce bu tabloya bak.
|
||||
|
||||
**Toolbar** (Grid/Tree/Card ve form sayfası; sıra sabittir — arama, ekle, yenile, rapor, akış, aç/kapa…;
|
||||
`toolbarOrder.ts`):
|
||||
|
||||
| Öğe | Açan | Not |
|
||||
| --- | --- | --- |
|
||||
| Arama | `SearchPanelJson.Visible` | |
|
||||
| Ekle | `AllowAdding` + `C` | `AddDialogName` > `AddPageUrl` > popup |
|
||||
| Yenile | her zaman | Widget'ları da yeniler |
|
||||
| Akış: Başlat / onay düğümleri / Sıfırla | `WorkflowJson` (`lowcode` §4.7) + `UpdateServiceAddress` dolu; Sıfırla için `ApprovalIsResetWorkflow` | Çoklu seçimde her satıra uygulanır |
|
||||
| Tümünü genişlet/daralt | Tree görünümü | |
|
||||
| Kolon seçici · Grup paneli | `ColumnOptionJson.ColumnChooserEnabled` · `GroupPanelJson.Visible` | |
|
||||
| Seçilileri sil | `AllowDeleting` + `D` | 2+ satır seçiliyken |
|
||||
| Tümünü sil (filtreli) | + `AllowAllDeleting` | Sayıyı gösterip onaylatır |
|
||||
| Batch Kaydet / Geri al | `Mode: batch` + `AllowUpdating` + `U` | |
|
||||
| Filtre uygula | `FilterRowJson.ApplyFilter: onClick` | |
|
||||
| Rapor › Liste | `FilterRowJson.AllowUserUiFilterSave` | `/admin/reports/DynamicGrid` (Tree'de `DynamicTree`) — filtre, sıralama, kolon genişlikleri ve alt form süzgeci taşınır (`lowcode` §9.12). Form sayfasında **Rapor › Form** |
|
||||
| Filtreyi kaydet/sil/temizle + kayıtlı filtre kutusu | `AllowUserUiFilterSave` | `UserUiFilter`; rol/genel paylaşılabilir (§2.5) |
|
||||
| Sütunları sığdır | (`AllowUserUiFilterSave` ya da `StateStoringJson.Enabled`) + `ColumnOptionJson.ColumnAutoWidth` | |
|
||||
| Grid durumunu kaydet/sıfırla | `StateStoringJson.Enabled` | Elle kayıt (§2.5) |
|
||||
| İçe aktar | `PermissionJson.I` | Aşağıda |
|
||||
| Dışa aktar | `ExportJson.Enabled` + `PermissionJson.E` (+ `AllowExportSelectedData`) | Grid: `pdf`, `xlsx`; Pivot: `xlsx`; Card/Tree/Gantt/Scheduler'da yok |
|
||||
| Ek filtre çubuğu | `ExtraFilterJson` | Grid, Tree, Card (`lowcode` §4.3.8) |
|
||||
| Yetkili kullanıcılar · Yönet | `App.Listforms.Listform.Update` | Ekranın R/C/U/D/E/I/N yetkisine sahip kullanıcı/rolleri listeler · ListForm editörünü açar (bütün görünümler + form sayfası) |
|
||||
| Özel butonlar | `CommandColumnJson` (`lowcode` §4.9) | Grid, Tree, Card, Todo (yalnız Url/OnClick) ve form sayfası; Gantt/Scheduler/Pivot/Chart'ta yok |
|
||||
|
||||
**Satır butonları:** Düzenle (`AllowUpdating` + `U`), Sil (`AllowDeleting` + `D`), Detay (`AllowDetail` +
|
||||
**`U`**), Not (`ShowNote` + `PermissionJson.N`), Kopyala (`AllowDuplicate` + `C`), özel butonlar. Card'da
|
||||
butonlar kart başlığındadır; form sayfasında Düzenle/Sil/Detay dışındaki satır butonları ve toolbar
|
||||
butonları **form toolbar'ına taşınır**.
|
||||
|
||||
**URL parametreleri** — menü/buton/widget adresinden ekranı süzülmüş ya da önceden doldurulmuş açmak için:
|
||||
|
||||
| Adres | Etki |
|
||||
| --- | --- |
|
||||
| `/admin/list/{kod}?filter=<DevExtreme filtre JSON>` | Sorguya `AND` eklenir; yeni satırda o alanlar bu değerle **dolu ve salt okunur** açılır; rapora taşınır |
|
||||
| `/admin/list/{kod}?{Alan}=değer` | Grid'deki her kolon için `=` süzgeci |
|
||||
| `/admin/list/{kod}?sort=[{"selector":"X","desc":true}]` | Açılış sıralaması |
|
||||
| `/admin/form/{kod}?{Alan}=değer` | Yeni kayıtta alan doldurulur ve kilitlenir |
|
||||
| `/admin/form/{kod}/{id}?filter=…` | Id süzgecine ek süzgeç |
|
||||
| `/admin/form/{kod}/{id}#{AltFormKodu}` | O alt form sekmesi seçili açılır |
|
||||
| `/admin/chart/{kod}?filter=…` | Grafik verisini süzer |
|
||||
| Yazma istekleri | Sayfanın URL parametreleri yazma isteğine query olarak eklenir → `CustomValueType: 4` QueryParams (`lowcode` §4.3.5) |
|
||||
|
||||
**Not paneli** (satırdaki Not butonu ya da form sayfasının yan paneli; alt formda yok): `note`/`message`
|
||||
türünde not, iş akışı kararları (`workflow` türü), dosya eki (dosya başına **2 MB**, indir/sil) ve
|
||||
**Değişiklik geçmişi** sekmesi (kaydın audit log'u, son 200 Insert/Update/Delete). Ayrı ek/geçmiş ekranı
|
||||
kurulmaz.
|
||||
|
||||
**İçe aktarma** (`PermissionJson.I`): Excel/CSV şablonu indirilir (kolonlar alan yetkisi `C` olanlar, `Id`
|
||||
hariç); `.xlsx/.xls/.csv`, en çok **10 MB**; önizlemede satır seçimi, oturum ve çalıştırma geçmişi. Yalnız
|
||||
**INSERT** yapar ve `QueryManager`'dan geçer: `Insert*Command` kancaları çalışır, **`InsertServiceAddress`
|
||||
atlanır**.
|
||||
|
||||
**Görünüme göre farklar:** Card'da kart başına 1–5 kolon seçici (tarayıcıda saklanır), dışa aktarma/
|
||||
sütun sığdırma/grup paneli/kaydet-sıfırla yok, koşullu biçim yok. Chart'ta arama kutusu görünür,
|
||||
`AllowSearch` açık metin kolonlarında `contains` ile OR'lanır ve URL `filter`'ının **yerine geçer**; "Seriler"
|
||||
çekmecesi herkese görünür, kaydetmek `App.Listforms.Listform` ister. Ek filtre metin kutusu ve Chart
|
||||
araması Enter ile uygulanır. Gantt, Scheduler, Todo ayrıntıları §7.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -518,6 +666,12 @@ ListForm editöründen açılır ve seed karşılığı elle yazılır.
|
|||
| `ChartHeight` | `320` |
|
||||
| `ChartCommonSeriesType` | `"bar"` |
|
||||
|
||||
Pivot başka bloklardan da okur: `allowFiltering` ← `FilterRowJson.Visible`, sıralama ← `SortMode != "none"`,
|
||||
başlık filtresinde "tümünü seç" ← `SelectionJson.AllowSelectAll`, `HeaderFilterJson` boyut/arama,
|
||||
`PagerOptionJson.ScrollingMode`/`LoadPanel*`, `ColumnOptionJson.ShowBorders/RtlEnabled/HoverStateEnabled`.
|
||||
Toolbar: "Grafiği göster", filtreyi temizle, kaydet/sıfırla (her zaman), dışa aktar (yalnız `xlsx`,
|
||||
yalnız `ExportJson.Enabled` — `E` yetkisine bakmaz). Koşullu biçim uygulanır; özel buton çizilmez.
|
||||
|
||||
### 6.2 Alan başına `PivotSettingsJson` (`ListFormFieldPivotSettingsDto`)
|
||||
|
||||
| Anahtar | Varsayılan | Değerler |
|
||||
|
|
@ -525,13 +679,15 @@ ListForm editöründen açılır ve seed karşılığı elle yazılır.
|
|||
| `IsPivot` | `true` | Alan pivotta kullanılsın mı |
|
||||
| `Area` | `filter` | `row` \| `column` \| `data` \| `filter` |
|
||||
| `SummaryType` | — | `sum` \| `avg` \| `count` \| `min` \| `max` |
|
||||
| `GroupInterval` | `none` | `day` \| `dayOfWeek` \| `month` \| `quarter` \| `year` |
|
||||
| `GroupInterval` | `""` | `day` \| `dayOfWeek` \| `month` \| `quarter` \| `year` |
|
||||
| `SortOrder` | `asc` | `asc` \| `desc` |
|
||||
| `Format` | — | DevExtreme format adı |
|
||||
| `Expanded` | `false` | Başlangıçta açık |
|
||||
| `WordWrapEnabled` | `false` | |
|
||||
|
||||
Pivot ekranı ayrı bir sorgu istemez; ızgarayla aynı `SelectCommand` üzerinden çalışır.
|
||||
Pivot ekranı ayrı bir sorgu istemez; ızgarayla aynı `SelectCommand` üzerinden çalışır. `PivotSettingsJson`'ı
|
||||
olmayan alan da DTO varsayılanıyla (`IsPivot: true`, `Area: filter`) **alan listesinde görünür** —
|
||||
pivotta istenmeyen alana `{"IsPivot": false}` yaz.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -546,14 +702,18 @@ DTO'daki `TitleExpr`/`StartExpr`/`EndExpr`/`ProgressExpr` ağaçta okunmaz — G
|
|||
|
||||
### 7.2 `GanttOptionJson` (`GanttOptionDto`)
|
||||
|
||||
Ağaç alanlarının tamamı + `TitleExpr`*, `StartExpr`*, `EndExpr`*, `ProgressExpr`*
|
||||
(istemci dördü olmadan görünümü açmaz — `List.tsx` `isLayoutValid`), `ScaleType` (varsayılan
|
||||
`KeyExpr`*, `ParentIdExpr`*, `RootValue` + `TitleExpr`*, `StartExpr`*, `EndExpr`*, `ProgressExpr`*
|
||||
(istemci altısı olmadan görünümü açmaz — `List.tsx` `isLayoutValid`; ağacın `HasItemsExpr`,
|
||||
`ExpandedRowKeys`, `AutoExpandAll`, `RecursiveSelection` alanları Gantt'ta **okunmaz**), `ScaleType` (varsayılan
|
||||
`weeks`; DevExtreme `GanttScaleType`: `auto` \| `minutes` \| `hours` \| `sixHours` \| `days` \|
|
||||
`weeks` \| `months` \| `quarters` \| `years`; kullanıcının seçtiği ölçek grid durumuyla saklanır)
|
||||
ve düzenleme bayrakları: **`EditingEnabled`** (ana anahtar — `AllowEditing` diye bir alan yoktur,
|
||||
yazılırsa düşer), `AllowTaskAdding`, `AllowTaskUpdating`, `AllowTaskResourceUpdating`,
|
||||
`AllowTaskDeleting`, `AllowDependencyAdding`, `AllowDependencyDeleting`, `AllowResourceAdding`,
|
||||
`AllowResourceUpdating`, `AllowResourceDeleting` (hepsi `false`).
|
||||
`AllowResourceUpdating`, `AllowResourceDeleting` (hepsi `false`). Bağımlılık ve kaynak veri kaynağı
|
||||
olmadığı için `AllowDependency*`/`AllowResource*` **işlevsizdir**; Gantt `PermissionJson` C/U/D'ye bakmaz,
|
||||
düzenlemeyi yalnız bu bayraklar yönetir. Toolbar: geri al/yinele, aç/kapa, yakınlaştırma, ölçek,
|
||||
filtre kaydet/sil/temizle, `StateStoringJson.Enabled` ise kaydet/sıfırla (görev listesi genişliği dahil).
|
||||
|
||||
### 7.3 `SchedulerOptionJson` (`SchedulerOptionDto`)
|
||||
|
||||
|
|
@ -563,7 +723,7 @@ yazılırsa düşer), `AllowTaskAdding`, `AllowTaskUpdating`, `AllowTaskResource
|
|||
| `UserNameExpr` · `DescriptionExpr` | — | Randevu sahibinin kullanıcı adı (kartta avatarı çizilir) ve açıklama |
|
||||
| `AllDayExpr` | — | Tüm gün bayrağı kolonu |
|
||||
| `RecurrenceRuleExpr` · `RecurrenceExceptionExpr` | — | Tekrar kuralı kolonları |
|
||||
| `StartDayHour` / `EndDayHour` | `8` / `20` | Görünen saat aralığı |
|
||||
| `StartDayHour` / `EndDayHour` | `8` / `20` | Görünen saat aralığı (`0` geçerlidir) |
|
||||
| `DefaultView` | `"week"` | Ekranın çizdiği sekiz görünüm: `day` \| `week` \| `workWeek` \| `month` \| `timelineDay` \| `timelineWeek` \| `timelineMonth` \| `agenda` |
|
||||
| `ShowAllDayPanel` | `true` | |
|
||||
| `CellDuration` | `30` | Hücre dakikası |
|
||||
|
|
@ -574,8 +734,11 @@ yazılırsa düşer), `AllowTaskAdding`, `AllowTaskUpdating`, `AllowTaskResource
|
|||
> **`Resources[]` bugün çalışmaz.** UI modeli (`proxy/form/models.ts`) ve `SchedulerView`
|
||||
> randevuları renklendiren kaynak eşlemesini (`FieldExpr`, `DataSource[]`, `Label`,
|
||||
> `UseColorAsDefault`) okur, ama C# `SchedulerOptionDto`'da alan yoktur — girişteki kural gereği
|
||||
> sunucu anahtarı düşürür, seed'e yazılan değer istemciye hiç ulaşmaz. Gerekirse önce DTO'ya
|
||||
> geriye dönük uyumlu alan eklenir.
|
||||
> sunucu anahtarı düşürür, seed'e yazılan değer istemciye hiç ulaşmaz. DTO'ya alan eklemek Core'dur
|
||||
> (`lowcode` §0.8); kaynağa göre renk ayrımı bugün kurulamaz, ihtiyaç "Core gerektiren kısım" notudur.
|
||||
|
||||
Scheduler'da not, iş akışı ve özel buton yoktur; düzenleme yalnız `SchedulerOptionJson.Allow*` ile yönetilir,
|
||||
`PermissionJson`'a bakmaz. Koşullu biçim uygulanmaz.
|
||||
|
||||
### 7.4 `TodoOptionJson` (`TodoOptionDto`) — Kanban
|
||||
|
||||
|
|
@ -583,6 +746,14 @@ yazılırsa düşer), `AllowTaskAdding`, `AllowTaskUpdating`, `AllowTaskResource
|
|||
`PriorityExpr`, `CompletedExpr`, `OrderExpr`, `TimesheetExpr`, `SubTaskExpr`,
|
||||
`StatusOrder` (kolon sırası, virgüllü), `AllowDragging` (varsayılan `true`).
|
||||
|
||||
- En fazla **1000 kayıt** yükler. Panodan kolon eklenir/yeniden adlandırılır; yeniden adlandırma bütün
|
||||
satırları günceller ve `UpdateServiceAddress` ister. Kolon düzeni `todo-` durumuna otomatik kaydedilir
|
||||
(`StateStoringJson.SavingTimeout` debounce).
|
||||
- Ekle/düzenle/sil yalnız `EditingOptionJson` + servis adreslerine bakar, `PermissionJson`'a bakmaz.
|
||||
Toolbar'da yalnız `Url`/`OnClick` tipli özel butonlar çizilir. `backlog`, `in progress` gibi bazı durum
|
||||
adları otomatik çevrilir.
|
||||
- Detay ekranında Ctrl/Cmd+S kaydeder, Esc sürüklemeyi iptal eder.
|
||||
|
||||
Panonun yüksekliği `TodoOptionJson` ile değil ekranın `Height` kolonuyla belirlenir; boş
|
||||
bırakıldığında pano sayfanın kalan yüksekliğini kaplar ve her kolon kendi içinde kayar.
|
||||
|
||||
|
|
@ -618,39 +789,41 @@ Grafik iki yoldan açılır: ekranın `LayoutJson.Chart` bayrağıyla bir görü
|
|||
| `AnimationJson` | Animasyon |
|
||||
| `ExportJson` | Dışa aktarma/yazdırma |
|
||||
|
||||
Kullanıcı/rol bazlı farklı grafik, ekranın `UserId`/`RoleId` varyantıyla kurulur (§5.7); boşsa
|
||||
grafik herkese aynıdır.
|
||||
Ekranın `UserId`/`RoleId` varyantı **okunmaz** (§5.7); kullanıcıya özel grafik yalnız seri bazında
|
||||
`ChartSeriesDto.UserId` ile verilir.
|
||||
|
||||
### 8.1 `SeriesJson` (`ChartSeriesDto[]`)
|
||||
|
||||
| Anahtar | Varsayılan | Anlam |
|
||||
| --- | --- | --- |
|
||||
| `Name` | — | Açıklamada görünen seri adı |
|
||||
| `Type` | — (DevExtreme: `line`) | `line` \| `stepline` \| `spline` \| `bar` \| `area` \| `splinearea` \| `steparea` \| `scatter` \| `bubble` \| `rangebar` \| `rangearea` \| `candlestick` \| `stock` \| `stackedbar` \| `stackedarea` \| `stackedline` \| `stackedspline` \| `stackedsplinearea` \| `fullstackedbar` \| `fullstackedarea` \| `fullstackedline` \| `fullstackedspline` \| `fullstackedsplinearea` (ListForm editörünün listesi: `chartSeriesTypeOptions`) |
|
||||
| `Type` | — (DevExtreme: `line`) | Değer küçük harfli `value`'dur (`fullstackedbar`); etiketle (`"Fullstacked Bar"`) kaydedilmiş eski seri çizimde değere çevrilir. Seçenekler: `line` \| `stepline` \| `spline` \| `bar` \| `area` \| `splinearea` \| `steparea` \| `scatter` \| `bubble` \| `rangebar` \| `rangearea` \| `candlestick` \| `stock` \| `stackedbar` \| `stackedarea` \| `stackedline` \| `stackedspline` \| `stackedsplinearea` \| `fullstackedbar` \| `fullstackedarea` \| `fullstackedline` \| `fullstackedspline` \| `fullstackedsplinearea` (ListForm editörünün listesi: `chartSeriesTypeOptions`) |
|
||||
| `ArgumentField` | `"arg"` | X ekseni kolonu — ekranın sorgusundaki bir **alan adı** |
|
||||
| `ValueField` | — | Y ekseni kolonu |
|
||||
| `SummaryType` | `"sum"` | `sum` \| `avg` \| `count` \| `min` \| `max` — sunucuda `ArgumentField` kırılımıyla toplanır (§8.2) |
|
||||
| `SummaryType` | `"sum"` (yalnız DTO) | `sum` \| `avg` \| `count` \| `min` \| `max` — özetsiz seri gruplu istekte değer üretmez (§8.2) |
|
||||
| `Color` | — | Seri rengi |
|
||||
| `Axis` · `Pane` | — | Hangi eksen/bölme |
|
||||
| `Axis` | — | Hangi değer ekseni (`ValueAxisJson[].Name`) |
|
||||
| `Visible` | `true` | |
|
||||
| `ShowInLegend` | `true` | |
|
||||
| `Width` | `2` | Çizgi kalınlığı |
|
||||
| `DashStyle` | `"solid"` | `solid` \| `dash` \| `dot` \| `longDash` |
|
||||
| `BarWidth` · `BarPadding` · `BarOverlapGroup` · `CornerRadius` | — | Çubuk serileri |
|
||||
| `IgnoreEmptyPoints` | `false` | |
|
||||
| `SelectionMode` | `"none"` | `onlyPoint` \| `allSeriesPoints` \| `allArgumentPoints` \| `includePoints` \| `excludePoints` \| `none` |
|
||||
| `RangeValue1Field` / `RangeValue2Field` | `val1` / `val2` | Aralık serileri |
|
||||
| `Label` | — | `ChartLabelDto`: `Visible`, `Format`, `Font`, `BackgroundColor`, `CustomizeText` |
|
||||
| `Pane` · `BarWidth` · `BarPadding` · `BarOverlapGroup` · `CornerRadius` · `IgnoreEmptyPoints` · `SelectionMode` · `RangeValue1Field`/`RangeValue2Field` | — | **Seri bazında okunmaz** (`buildSeriesDto` seriye geçirmez) — yalnız `CommonSeriesSettingsJson` üzerinden etkilidir |
|
||||
| `Label` | — | `ChartLabelDto`: `Visible` (`false`), `Format`, `Font`, `BackgroundColor` (`#f05b41`). `CustomizeText` metin olarak geçer, DevExtreme fonksiyon beklediği için etkisizdir |
|
||||
| `UserId` | — | Kullanıcı adı (`UserName`, kimlik değil). O kullanıcının kendi serisi varsa **yalnızca** onun serileri çizilir, yoksa `UserId`'si ne olursa olsun bütün seriler. Kullanıcı grafik çekmecesinden kendi serisini kaydettiğinde bu alan dolar |
|
||||
|
||||
### 8.2 Veri — grafik ekranın kendi sorgusundan beslenir
|
||||
|
||||
Grafik ayrı bir sorgu çalıştırmaz: ekranın `SelectCommand`'ı (ve `DefaultFilter`, kırılım
|
||||
İstemci grafiği ekranın `SelectCommand`'ı (ve `DefaultFilter`, kırılım
|
||||
filtreleri, kullanıcının o anki filtresi) üzerinde, serilerin `ArgumentField` değerleriyle
|
||||
**gruplanmış** ve her serinin `ValueField` + `SummaryType` çiftiyle **özetlenmiş** bir istek atılır
|
||||
(`useListFormCustomDataSource`, `layoutTypes.chart`). Yani `SELECT … GROUP BY` yazmaya gerek yoktur;
|
||||
özetlenecek ham satırları döndüren sorgu yeter. Farklı kırılımda ikinci bir grafik gerekiyorsa
|
||||
ikinci bir ListForm (ya da view) açılır.
|
||||
ikinci bir ListForm (ya da view) açılır. Birden çok farklı `ArgumentField` iç içe gruplanır; özet
|
||||
değerleri **seri sırasına göre** eşlenir — `ValueField`/`SummaryType` eksik bir seri sonrakileri kaydırır,
|
||||
aynı `ValueField` iki seride farklı özetle kullanılırsa sonuncusu kazanır.
|
||||
|
||||
Özet, liste sorgusunun grup yolundan (`GroupQuery`) üretilir; iki sağlayıcıda da aynı çalışır. Ayrı bir
|
||||
grafik sorgusu yoktur.
|
||||
|
||||
`DataSourceJson` kolonu ve `ChartDataSourceDto { Query }` / `ChartDataRequestDto` tipleri kodda
|
||||
durur ama **okunmaz** — oraya sorgu yazmak grafiği değiştirmez.
|
||||
|
|
@ -689,7 +862,7 @@ durur ama **okunmaz** — oraya sorgu yazmak grafiği değiştirmez.
|
|||
`WorkdaysOnly` (`false`), `Position` (`bottom` \| `left` \| `right` \| `top`),
|
||||
`HoverMode` (`none` \| `allArgumentPoints`), `Grid` (`ChartAxisGridDto`: `Visible`, `Color`
|
||||
`#d3d3d3`, `Width` `1`), `Label` → `DisplayMode` (`standard` \| `rotate` \| `stagger`),
|
||||
`RotationAngle` (`90`), `OverlappingBehavior` (`hide` \| `stagger` \| `none`). Argüman alanında
|
||||
`RotationAngle` (`90`), `OverlappingBehavior` (`rotate` \| `stagger` \| `none` \| `hide`). Argüman alanında
|
||||
lookup varsa etiket metni lookup'ın görünen değerine otomatik çevrilir.
|
||||
|
||||
`ValueAxisJson` bir **dizidir** (`ChartValueAxisDto[]`; çok eksenli grafik — seri `Axis` alanıyla
|
||||
|
|
@ -699,38 +872,45 @@ lookup varsa etiket metni lookup'ın görünen değerine otomatik çevrilir.
|
|||
`AutoBreaksEnabled` (`true`), `MaxAutoBreakCount` (`2`). Tek nesne yazmak `JsonException` verir.
|
||||
|
||||
`CommonAxisSettingsJson` (`ChartCommonAxisDto`: `Title`, `Visible`, `Width`, `Grid`) iki eksene
|
||||
birden uygulanır; **eksene özel ayar varsa yok sayılır.**
|
||||
birden uygulanır; **eksene özel ayar varsa yok sayılır.** `ArgumentAxisJson` sunucudan her zaman dolu
|
||||
döndüğü için argüman ekseninde fiilen hiç etkili olmaz; değer ekseninde yalnız `ValueAxisJson` boş (`[]`)
|
||||
iken etkilidir. `ChartAxisGridDto.Visible` varsayılanı `false`'tur.
|
||||
|
||||
### 8.6 `LegendJson` (`ChartLegendDto`)
|
||||
|
||||
`Visible` (`true`), `Position` (`outside` \| `inside`), `Orientation` (`vertical` \| `horizontal`),
|
||||
`ColumnCount`, `RowCount`, `Title`, `BackgroundColor`, `Border`.
|
||||
`ColumnCount` (`0`), `RowCount` (`0`), `Title`, `BackgroundColor`, `Border`.
|
||||
|
||||
### 8.7 `TooltipJson` (`ChartTooltipDto`)
|
||||
|
||||
`Enabled`, `Shared`, `Format` / `ArgumentFormat` (DevExtreme format adları),
|
||||
`Enabled` (**`false`** — `TooltipJson` boşsa ipucu kapalıdır; açmak için `{"Enabled": true}` yaz), `Shared`,
|
||||
`Format` / `ArgumentFormat` (DevExtreme format adları),
|
||||
`Color` (`#ffffff`), `ArrowLength` (`10`), `Location` (`center` \| `edge`),
|
||||
`PaddingLeftRight` (`18`), `PaddingTopBottom` (`15`), `Border`, `Font`.
|
||||
`PaddingLeftRight` (`18`), `PaddingTopBottom` (`15`), `Border`, `Font` (ipucu fontunun rengi `#000000`).
|
||||
|
||||
### 8.8 Diğerleri
|
||||
|
||||
- `PanesJson` (`ChartPanesDto[]`): `Name`, `Height` (`250`), `BackgroundColor`.
|
||||
Seriler `Pane` alanıyla bir bölmeye bağlanır.
|
||||
- `CrosshairJson` (`ChartCrosshairDto`): `Enabled`, `Color` (`#f05b41`), `Width` (`1`),
|
||||
`DashStyle` (`dot`), `HorizontalLine`, `VerticalLine`, `Label`.
|
||||
- `ScrollBarJson` (`ChartScrollBarDto`): `Visible`, `Position` (`top`), `Color` (`gray`),
|
||||
- `CrosshairJson` (`ChartCrosshairDto`): `Enabled` (`false`), `Color` (`#f05b41`), `Width` (`1`),
|
||||
`DashStyle` (`dot`), `HorizontalLine`/`VerticalLine` (`ChartCrosshairLineDto`: `Color` `#f05b41`,
|
||||
`DashStyle` `dot`, `Visible` `true`, `Width` `1`, `Label`), `Label`.
|
||||
- `ScrollBarJson` (`ChartScrollBarDto`): `Visible` (`false`), `Position` (`top`), `Color` (`gray`),
|
||||
`Width` (`10`), `Offset` (`5`).
|
||||
- `ZoomAndPanJson` (`ChartZoomAndPanDto`): `ArgumentAxis` / `ValueAxis`
|
||||
(`none` \| `pan` \| `zoom` \| `both`), `AllowMouseWheel` (`true`), `AllowTouchGestures` (`true`),
|
||||
`DragToZoom` (`false`), `PanKey` (`shift`), `DragBoxStyle`.
|
||||
`DragToZoom` (`false`), `PanKey` (`shift`), `DragBoxStyle` (`Color`, `Opacity` `0`).
|
||||
- `AnnotationsJson` (`ChartAnnotationDto[]`): `Name`, `Type` (`text` \| `image`), `Text`, `Image`,
|
||||
konum için `Series` + `Argument`/`Value` ya da piksel `X`/`Y`, `OffsetX`/`OffsetY` (`-1`),
|
||||
`Width`/`Height`, `PaddingLeftRight`/`PaddingTopBottom` (`10`), `WordWrap` (`normal`),
|
||||
`Width` (`0`)/`Height` (`-1`), `PaddingLeftRight`/`PaddingTopBottom` (`10`), `WordWrap` (`normal`),
|
||||
`Color` (`#ffffff`), `Font`, `Border`, `TooltipEnabled` (`true`), `Description`.
|
||||
`CommonAnnotationsSettingsJson` (`ChartCommonAnnotationDto`) aynı alanları `Name` olmadan taşır.
|
||||
- `CommonPaneSettingsJson` (`ChartCommonPaneDto`): yalnızca `BackgroundColor`.
|
||||
- Ortak alt nesneler: `Font` (`Color` `#FFFFFF`, `Family`, `Size` `12`, `Weight` `400`),
|
||||
`Border` (`Visible`, `Color` `#d3d3d3`, `Width` `1`, `CornerRadius` `0`, `DashStyle` `solid`).
|
||||
- Ortak alt nesneler: `Font` (`Color` `#FFFFFF`, `Family` `"Segoe UI", "Helvetica Neue", "Trebuchet MS",
|
||||
Verdana, sans-serif`, `Size` `12`, `Weight` `400`), `Border` (`Visible` `false`, `Color` `#d3d3d3`,
|
||||
`Width` `1`, `CornerRadius` `0`, `DashStyle` `solid`).
|
||||
- `ExportJson.Enabled` varsayılanı `false`'tur ve Grid/Pivot dışa aktarmayı da açar (§1, §5.8).
|
||||
`ChartOptionsRequestDto` kodda durur, kullanılmaz.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -744,7 +924,7 @@ dışında kalanlar:
|
|||
| Anahtar | Anlam |
|
||||
| --- | --- |
|
||||
| `AllowFiltering` | Bu sütun filtrelenebilsin mi (`true`) |
|
||||
| `FilterOperations[]` | İzin verilen operatörler; boş bırakılırsa tipe göre otomatik. Değerler: `=`, `<>`, `<`, `<=`, `>`, `>=`, `contains`, `notcontains`, `startswith`, `endswith`, `isblank`, `isnotblank`, `between`, `anyof`, `noneof` |
|
||||
| `FilterOperations[]` | **Ölü ayar** — istemci okumaz; operatörler DevExtreme'in tipe göre listesidir. DTO varsayılanı tipe göre: metin `contains, notcontains, startswith, endswith, =, <>`; sayı/tarih `=, <>, <, >, <=, >=, between` |
|
||||
| `SelectedFilterOperation` | Varsayılan seçili operatör |
|
||||
| `FilterValue` | Ekran açılırken uygulanan filtre değeri |
|
||||
|
||||
|
|
@ -760,31 +940,34 @@ dışında kalanlar:
|
|||
```
|
||||
|
||||
Anahtarlar PascalCase yazılır; `text`/`value` küçük harfle yazılırsa liste boş gelir (giriş, ortak
|
||||
kurallar). Ekranın `HeaderFilterJson.Visible` bayrağı kapalıysa bu liste de görünmez.
|
||||
kurallar). Eski `DataSourceString` alanı (aynı listenin metin hâli, `Obsolete`) getter'ı olduğu için JSON'a
|
||||
da yazılır; okunmaz, yazma. Ekranın `HeaderFilterJson.Visible` bayrağı kapalıysa bu liste de görünmez.
|
||||
|
||||
### 9.3 `GroupingJson` (`ColumnGroupingDto`)
|
||||
|
||||
`AllowGrouping` (`true`), `GroupIndex` (kaçıncı seviyeden gruplanacağı), `AutoExpandGroup` (`false`).
|
||||
`GroupIndex` verilen sütun ekran açılışında gruplanmış gelir.
|
||||
`GroupIndex` verilen sütun ekran açılışında gruplanmış gelir; istemci `if (groupIndex)` kullandığı için
|
||||
**`0` yok sayılır** — ilk seviye `1`'dir.
|
||||
|
||||
### 9.4 `ColumnCustomizationJson` (`ColumnCustomizationDto`)
|
||||
|
||||
`Fixed` (`false`), `FixedPosition` (`left` \| `right`), `AllowReordering` (`false`).
|
||||
Sol/sağa sabitlenmiş kolon yatay kaydırmada sabit kalır.
|
||||
`Fixed` (`false`), `FixedPosition` (`left` \| `right`), `AllowReordering` (`false`; wizard `true` yazar).
|
||||
Sol/sağa sabitlenmiş kolon yatay kaydırmada sabit kalır. Kolon başına `AllowReordering` yalnızca ekranın
|
||||
`ColumnOptionJson.AllowColumnReordering`'i açıksa etkilidir.
|
||||
|
||||
### 9.5 `TotalSummaryJson` / `GroupSummaryJson` (`ColumnTotalSummaryDto`)
|
||||
|
||||
| Anahtar | Anlam |
|
||||
| --- | --- |
|
||||
| `SummaryType` | `sum` \| `avg` \| `count` \| `min` \| `max` (`SummaryTypeEnum`; `custom` hesaplayıcısı bağlanmadığı için kullanılmaz) |
|
||||
| `SummaryType` | `sum` \| `avg` \| `count` \| `min` \| `max` — sunucu yalnızca bu beşini kabul eder (`SelectQueryManager.SummaryTypes`). C# enum'u yoktur; TS `SummaryTypeEnum`'unda ayrıca `none` vardır. `custom` hesaplayıcısı bağlanmadığı için kullanılmaz |
|
||||
| `ValueFormat` | DevExtreme format adı (`fixedPoint`, `currency`, `percent`, `shortDate`…) |
|
||||
| `DisplayFormat` | Metin şablonu: `{0}` biçimlenmiş değer, `{1}` `ShowInColumn`'daki sütunun başlığı |
|
||||
| `ShowInColumn` | Özetin hangi sütunun altında görüneceği (kolon adı). `DisplayFormat`'taki `{1}` bunun başlığıdır |
|
||||
| `ShowInGroupFooter` | `false` — grup alt bilgisinde göster (yalnızca `GroupSummaryJson`) |
|
||||
| `AlignByColumn` | `false` — grup satırında ilgili sütunun altına hizala; `false` iken özet grup başlığının yanında parantez içinde çıkar |
|
||||
| `ShowInGroupFooter` · `AlignByColumn` | **Ölü ayar** — yönetim formunda düzenlenir ama grid'in grup özetine (`Grid.tsx`) aktarılmaz; grup özeti her zaman grup başlığının yanında çıkar |
|
||||
|
||||
`TotalSummaryJson` listenin altındaki toplam satırını, `GroupSummaryJson` grup kırılımındaki
|
||||
özeti üretir; ikisi de **aynı DTO'yu** kullanır, fark yazıldıkları kolondur.
|
||||
özeti üretir; ikisi de **aynı DTO'yu** kullanır, fark yazıldıkları kolondur. Özetler yalnızca
|
||||
**Grid** görünümünde çizilir; Tree ve Card yok sayar.
|
||||
|
||||
"Listenin altında toplam görünsün" isteği budur; ayrı sorgu ya da widget gerekmez.
|
||||
|
||||
|
|
@ -794,43 +977,44 @@ Bir kolonu **başka bir tablodan** çekmek için; view yazmadan tek alanlık joi
|
|||
|
||||
| Anahtar | Anlam |
|
||||
| --- | --- |
|
||||
| `JoinType` | `INNER JOIN` | `LEFT JOIN` | `RIGHT JOIN` — kısaltma (`LEFT`, `INNER`) sorguda tam kalıba çevrilir, tanınmayan değer `LEFT JOIN` olur (`JoinTable.JoinClause`) |
|
||||
| `JoinType` | `INNER JOIN` · `LEFT JOIN` · `RIGHT JOIN` — kısaltma (`LEFT`, `INNER`) sorguda tam kalıba çevrilir, tanınmayan değer `LEFT JOIN` olur (`JoinTable.JoinClause`) |
|
||||
| `TableName` | Join kurulacak tablo |
|
||||
| `BaseTableJoinFieldName` | Ana tablonun join alanı |
|
||||
| `JoinFieldName` | Join kurulan tablonun ilişkili alanı |
|
||||
| `SelectFieldName` | Ekranda gösterilecek alan |
|
||||
| `FieldNameAlias` | Alanın takma adı |
|
||||
| `FieldNameAlias` | Alanın takma adı — doluysa kolon sorgudan **bu adla** döner; grid sütunu `FieldName`'e bağlı olduğu için boş kalır. Ekranda gösterilecek join alanında boş bırak |
|
||||
| `JoinCondition2` | İkinci koşulun bağlacı (`AND` varsayılan \| `OR`) |
|
||||
| `JoinFieldName2` | İkinci koşulun alanı — **tablo adıyla birlikte** (`Def_T_City.CultureName`) |
|
||||
| `BaseTableJoinFieldName2_OrValue` | İkinci koşulun karşı tarafı: tablo adlı bir alan ya da `'en'` gibi sabit |
|
||||
| `JoinFieldName2` | İkinci koşulun alanı: `Def_T_City.CultureName` ya da yalın `CultureName` (join tablosuna bağlanır); parçalar ayrı ayrı tırnaklanır |
|
||||
| `BaseTableJoinFieldName2_OrValue` | İkinci koşulun karşı tarafı: **ham** yazılır (tırnaklanmaz) — tablo adlı alan kendi tırnağıyla, sabit `'en'` gibi |
|
||||
|
||||
Üç-dört join'i geçen ihtiyaçta view tasarımcısı tercih edilir (`lowcode` §8.2).
|
||||
Aynı JOIN cümlesi birden çok alanda geçerse bir kez yazılır; join alanına filtre/sıralama
|
||||
`"Tablo"."SelectFieldName"`'e çevrilir. Üç-dört join'i geçen ihtiyaçta view tasarımcısı tercih edilir (`lowcode` §8.2).
|
||||
|
||||
### 9.7 Diğer alan kolonları
|
||||
|
||||
| Kolon | Varsayılan | Anlam |
|
||||
| --- | --- | --- |
|
||||
| `FieldName` | — | Kaynaktaki sütun adı; SQL'deki adıyla birebir |
|
||||
| `FieldName` | — | Kaynaktaki sütun adı; SQL'deki adıyla birebir. **`Kolon:Özellik`** biçimi (`Options:TemplateName`) JSON metin kolonunun tek özelliğini ayrı form alanı yapar: okurken JSON'dan doldurulur, kayıtta tek JSON'a birleştirilir; etiket özellik adıdır, yetki kök kolondan okunur |
|
||||
| `CaptionName` | — | Sütun başlığı — **dil anahtarı** |
|
||||
| `PlaceHolder` | — | Editörün placeholder metni |
|
||||
| `PlaceHolder` | — | Editörün placeholder metni — **dil anahtarı**; yalnızca düzenleme popup'ı, form sayfası ve Card'da görünür |
|
||||
| `Alignment` | `"left"` | `left` \| `center` \| `right` |
|
||||
| `Format` | — | Hücre biçimi (DevExtreme format adı ya da desen) |
|
||||
| `BandName` | — | Sütunu bir başlık bandının altına toplar |
|
||||
| `Width` · `ListOrderNo` | — | Genişlik ve grid'deki sıra |
|
||||
| `Visible` | — | Sütun grid'de görünür mü; `false` ise kolon seçicide durur ama **sorguya girer** |
|
||||
| `IsActive` | `true` | `false` olan alan **sorguya bile girmez** |
|
||||
| `SortIndex` · `SortDirection` | — | Açılıştaki sıralama (`asc` \| `desc`); çok sütunlu sıralamada `SortIndex` sırası belirler |
|
||||
| `AllowSearch` · `AllowEditing` · `AllowAdding` | `true` | Arama paneline dâhil olma, güncellemede ve yeni kayıtta düzenlenebilirlik |
|
||||
| `ColumnCssClass` · `ColumnCssValue` | — | Koşulsuz stil (sınıf adı + sınıfın içeriği); koşullu olan `ColumnStylingJson` |
|
||||
| `SourceDbType` | `16` String | Kolonun `System.Data.DbType` karşılığı |
|
||||
| `EditorType2` · `EditorOptions` · `EditorScript` | — | Editör tipi ve davranışı (`lowcode` §5, §6) |
|
||||
| `ColSpan` · `EditOrderNo` · `EditGroupOrderNo` | — | Düzenleme formundaki yeri; `EditGroupOrderNo` `EditingFormJson`'daki `Order` ile eşleşir |
|
||||
| `Format` | — | Hücre biçimi (DevExtreme format adı ya da desen); `EditorOptions.displayFormat`, sonra `EditorOptions.format` varsa onlar önce gelir |
|
||||
| `BandName` | — | Sütunu bir başlık bandının altına toplar; `Üst:Alt` ile en çok iki seviye. Band başlığı **düz metindir**, çevrilmez |
|
||||
| `Width` · `ListOrderNo` | — | Genişlik (`0` = otomatik, wizard varsayılanı; yalnızca `>0` uygulanır) ve grid'deki sıra |
|
||||
| `Visible` | — | Sütun grid'de görünür mü; `false` ise kolon seçicide durur ama **sorguya girer**. Entity'de `bool?`, DTO'da `bool` — her zaman açıkça yaz. Formda olup listede görünmeyen alan gizli grid kolonu olarak eklenir |
|
||||
| `IsActive` | `true` | `false` **ya da boş** olan alan sorguya da arayüze de girmez |
|
||||
| `SortIndex` · `SortDirection` | — | Açılıştaki sıralama (`asc` \| `desc`); sunucu yalnızca `SortIndex > 0` alanları artan sırayla kullanır (`0`/boş sıralamaya girmez) |
|
||||
| `AllowSearch` · `AllowEditing` · `AllowAdding` | `true` | Arama paneline dâhil olma (DTO varsayılanı `false` — `AllowSearch`'ü açıkça yaz). `AllowEditing`/`AllowAdding` = `false` alanı o modda formda **gizler** ve payload'dan atar (salt okunur yapmaz; salt okunurluk `EditorOptions.readOnly` ya da alan yetkisinin `U`/`C` eksikliğidir). Grid kolonunda `allowEditing = AllowEditing \|\| AllowAdding` |
|
||||
| `ColumnCssClass` · `ColumnCssValue` | — | Koşulsuz stil: sınıf adı + **tam CSS kuralı** (`.sinif{color:red}`) ya da `http…`/`/…` ile başlayan stylesheet adresi; `ColumnCssValue` yalnızca `ColumnCssClass` doluysa eklenir. Koşullu olan `ColumnStylingJson` |
|
||||
| `SourceDbType` | `0` (entity) · `16` (wizard) | Kolonun `System.Data.DbType` karşılığı. İstemci tipi (`DataType`) buradan türetilir: metin/Guid → `string`; Currency/Decimal/Double/Int*/Single/UInt* → `number`; Date → `date`; DateTime/DateTime2/DateTimeOffset → `datetime`; Boolean → `boolean`. **Byte/SByte/Binary/Time/Xml/VarNumeric boş tip verir** — `tinyint` kolonunu `Int16` olarak yaz ki sayı filtresi/biçimi çalışsın |
|
||||
| `EditorType2` · `EditorOptions` · `EditorScript` | — | Editör tipi ve davranışı (`lowcode` §5, §6). Liste etkisi: `dxHtmlEditor` `encodeHtml=false`, lookup'sız `dxColorBox` renk kutusu, `dxRating` sola hizalı; `EditorOptions.encodeHtml` kolon ayarını ezer |
|
||||
| `ColSpan` · `EditOrderNo` · `EditGroupOrderNo` | — | Düzenleme formundaki yeri; `EditGroupOrderNo` `EditingFormJson`'daki `Order` ile eşleşir. Alanın forma girip girmediğine **`EditOrderNo`** karar verir (boşsa girmez); `EditGroupOrderNo` boşsa 1. gruba düşer |
|
||||
| `PermissionJson` | — | Alan yetkileri (§5.1) |
|
||||
| `CultureName` · `UserId` · `RoleId` | — | Alan varyantı (§5.7) |
|
||||
|
||||
> **`DefaultValue` / `DefaultValueType` / `ReadOnly` diye bir alan kolonu yoktur.** İstemciye
|
||||
> giden `ColumnFormatDto`'da bu adlar görünür ama çıktı alanlarıdır; seed'e yazılan değer düşer.
|
||||
> Varsayılan değerler ekran seviyesindeki `Insert/Update/Delete/Form/SelectFieldsDefaultValueJson`
|
||||
> Varsayılan değerler ekran seviyesindeki `Insert/Update/Delete/FormFieldsDefaultValueJson`
|
||||
> bloklarında, alan adıyla eşleşen `FieldsDefaultValueDto` satırları olarak durur
|
||||
> (`lowcode` §4.3.5); salt okunurluk ise `EditorOptions.readOnly` ya da `EditorScript`'in
|
||||
> `readOnly` tarifidir (`lowcode` §6.6).
|
||||
|
|
@ -908,14 +1092,15 @@ Düğüm başına iki ortak prop, hangi ailede olursa olsun geçerlidir:
|
|||
> **Önce yeniden kullan:** İstenen şey bir ListForm ekranının verdiği liste/ağaç/pano/grafikse
|
||||
> primitiflerden kurma; `platform` düğümünü `listFormCode` ile bırak.
|
||||
>
|
||||
> **Eksik olan = var olan bileşene ekle, yeni bileşen yazma:** İstenen komponent bu
|
||||
> envanterle büyük ölçüde kuruluyor ama bir bileşende **olay, prop ya da küçük bir yetenek**
|
||||
> eksikse komponent yine üretilir: eksik parça `components/ui/{Name}`'e geriye dönük uyumlu
|
||||
> eklenir, `componentProps.json` elle güncellenir, olaysa `catalog.ts` `DESIGNER_PRIMARY_EVENTS`,
|
||||
> **Eksik olan = Core, komutla eklenir:** İstenen komponent bu envanterle büyük ölçüde kuruluyor
|
||||
> ama bir bileşende **olay, prop ya da küçük bir yetenek** eksikse komponent kurulabildiği kadar
|
||||
> üretilir, eksik parça son mesajda "Core gerektiren kısım" notuyla bildirilir. Kullanıcı
|
||||
> **"core sisteme ekle"** derse parça `components/ui/{Name}`'e geriye dönük uyumlu eklenir,
|
||||
> `componentProps.json` elle güncellenir, olaysa `catalog.ts` `DESIGNER_PRIMARY_EVENTS`,
|
||||
> değer kümesiyse `NAMED_UNION_OPTIONS`/`PROPERTY_OVERRIDES`, sonra §10.9/§10.10 tabloları
|
||||
> tamamlanır (`lowcode` §7.3 notu). Yeni `ui` bileşeni, yeni toolbox ailesi, Developer Kit
|
||||
> menüsüne yeni komponent ya da var olan bileşenin davranışını değiştiren ekleme **yapılmaz** —
|
||||
> bunlar çerçeve dışıdır ve onay ister (`lowcode` §0.8).
|
||||
> menüsüne yeni komponent ya da var olan bileşenin davranışını değiştiren ekleme komut olmadan
|
||||
> **yapılmaz** (`lowcode` §0.8).
|
||||
|
||||
### 10.2 `Form` düğümü
|
||||
|
||||
|
|
@ -1436,7 +1621,7 @@ eklerken `BranchId` de yazılır.
|
|||
|
||||
Bu ekranlar `Sas_H_Route` kayıtlarıyla yönetilir (seed:
|
||||
`configs/seeds/data/App.Menus.Routes.json`). Yenisini eklemek **kod yazmak demektir** — karar
|
||||
sırasının son adımıdır ve çerçeve dışıdır (onay ister, `lowcode` §0.8). Rotalı bir sayfa ihtiyacının
|
||||
sırasının son adımıdır ve Core'dur (yalnızca "core sisteme ekle" komutuyla, `lowcode` §0.8). Rotalı bir sayfa ihtiyacının
|
||||
çerçeve içi karşılığı `RoutePath` taşıyan bir custom component'tir.
|
||||
|
||||
Bir route kaydının alanları: `Id`, `Key`, `Path`, `ComponentType`, `ComponentPath` (`@/views/...`),
|
||||
|
|
@ -1599,9 +1784,10 @@ belirleyicidir**:
|
|||
|
||||
| Nereye | Bilinmeyen anahtara ne olur |
|
||||
| --- | --- |
|
||||
| Ekran seviyesindeki `*Json` kolonları (§2–§8) | **Düşer.** `GridOptionsDto` ham metni `[JsonIgnore]` ile gizler, istemciye yalnızca tipli DTO gider. Kalıcı olarak gerekiyorsa önce ilgili DTO'ya alan eklenir, sonra bu dosya güncellenir |
|
||||
| Ekran seviyesindeki `*Json` kolonları (§2–§8) | **Düşer.** `GridOptionsDto` ham metni `[JsonIgnore]` ile gizler, istemciye yalnızca tipli DTO gider. DTO'ya alan eklemek Core'dur — yalnızca "core sisteme ekle" komutuyla, sonra bu dosya güncellenir |
|
||||
| Alan seviyesindeki `ListFormField.EditorOptions` (§9.8) | **Geçer.** Ham metin olarak istemciye iner ve editöre olduğu gibi verilir; sözlükte olmayan anahtar Options Builder'ın "Sözlük dışı ayarlar" bölümünden de yazılabilir (`lowcode` §6.1) |
|
||||
| `CustomJsSourcesJson` / `CustomStyleSourcesJson` (§5.5) | Geçer — ama son çaredir, denetlenmez |
|
||||
|
||||
Yani "DevExtreme'de var, platformda yok" durumunda önce §9.8'e (editör seçeneği mi?) bak; ekran
|
||||
seviyesindeki bir seçenekse DTO'ya eklenmeden çalışmayacağını bilerek planla.
|
||||
seviyesindeki bir seçenekse DTO'ya eklenmeden çalışmaz: önce envanterdeki karşılığını kur, yoksa
|
||||
"Core gerektiren kısım" notuyla bildir (`lowcode` §0.8).
|
||||
|
|
|
|||
410
.github/instructions/lowcode.instructions.md
vendored
410
.github/instructions/lowcode.instructions.md
vendored
|
|
@ -294,7 +294,7 @@ Akış : Onay adımları ve onaycılar
|
|||
Otomasyon : Zamanlanmış iş / bildirim / mail gerekiyor mu
|
||||
Menü : Üst menü, sıra, ikon
|
||||
Yetki : Grup adı + kimde hangi yetki
|
||||
Eklemeler : Hangi ui bileşenine hangi olay/prop/küçük yetenek eklenecek (§7.3) — yeni bileşen yok
|
||||
Core : Çerçeve içinde karşılanamayan kısım (yoksa "yok") — yalnızca not, komutsuz yazılmaz (§0.8)
|
||||
Kapsam : IsTenant / IsBranch / IsOrganizationUnit
|
||||
Dil : EN + TR metinler
|
||||
Üretilecek : Dosya listesi (§0.1 klasörlerine göre)
|
||||
|
|
@ -387,7 +387,7 @@ Bunlar bir ekran görüntüsünde **görünmez**; varsayımını yaz ve bildir:
|
|||
| Tenant/şube kırılımı | `IsTenant: true` (§CLAUDE varsayılanı) |
|
||||
| Yetki grubu ve menü kökü | Ekranın ait olduğu modülden türet, kullanıcıya sor değil bildir |
|
||||
| Dil metinleri | Görseldeki dilde yaz, diğer dile çevir; ikisi de doldurulur |
|
||||
| Onaycılar | Yer tutucu bırak (`<roleOrUserId>`) ve kullanıcıya sor — **bu, sorulması gereken bir şeydir** |
|
||||
| Onaycılar | Yer tutucu bırak (`<userName>` / `<email>` ya da `@Kolon`) ve kullanıcıya sor — **bu, sorulması gereken bir şeydir** |
|
||||
| İş kuralları (hesap, koşul) | Görselde formül görünmüyorsa `EditorScript` yazma; sor |
|
||||
|
||||
#### 0.7.5 Görsel için de aynı protokol
|
||||
|
|
@ -400,37 +400,63 @@ sonunda açıkça yaz.
|
|||
|
||||
---
|
||||
|
||||
### 0.8 Çerçeve sınırı — uygulama kendini geliştirir, dışına çıkmaz
|
||||
### 0.8 Çerçeve sınırı — Core'a yeni özellik yalnızca komutla
|
||||
|
||||
Platform kendi mekanizmalarıyla büyür; **çerçevenin dışına çıkan her talep üretimden önce
|
||||
kullanıcıya sorulur ve yalnızca onayla yapılır.** "Yapılamaz" cevabı yoktur, "sormadan
|
||||
çerçeve dışına çık" da yoktur.
|
||||
Platform kendi mekanizmalarıyla büyür. **Core**, `api/` ve `ui/` altındaki kaynak kodun tamamıdır;
|
||||
çerçeve ise `configs/seeds/` altında üretilen artefaktlardır. Kullanıcı **"core sisteme ekle"**
|
||||
(ya da core değişikliğini adıyla isteyen eşdeğer bir komut: "`GridEditingDto`'ya alan ekle",
|
||||
"`Button` bileşenine `onBlur` ekle", "şu servisi kodda değiştir") demedikçe Core'a **yeni bir
|
||||
özellik** eklenmez. Küçük olması, geriye dönük uyumlu olması ya da işi tamamlaması izin sayılmaz;
|
||||
tek satırlık bir DTO alanı, prop, olay, tarif, `EditorOptions` anahtarı ya da `DefaultValue`
|
||||
token'ı da yeni özelliktir.
|
||||
|
||||
**Önce envanter.** "Core gerekiyor" sonucuna, ListForm'un bütün yetenekleri taranmadan varılmaz:
|
||||
`lowcode-reference.instructions.md` §0 katman listesi (24 katman), §1–§9 JSON kolonları, bu
|
||||
dosyanın §4 (wizard/alan/lookup/varsayılan/doğrulama/biçim/ek filtre/alt form/widget/iş akışı/
|
||||
komut butonları), §5 `EditorScript`, §6 `EditorOptions` (alan seviyesinde sözlük dışı anahtar
|
||||
da geçer), §7 Custom Component, §8–§9 SQL nesnesi, Custom Endpoint, Dynamic Service,
|
||||
BackgroundWorker, bildirim, rapor. Talebin karşılığı çoğunlukla bunların birleşimidir:
|
||||
ekranda yapılamayan yazma `*Command`/Before-After kancasıdır, ekranda olmayan aksiyon
|
||||
`CommandColumnJson` butonu + Custom Endpoint'tir, hesap `EditorScript`'tir, ekran dışı iş
|
||||
mantığı Dynamic Service'tir.
|
||||
|
||||
**Çerçeve içi — sormadan yapılır** (keşif turu tarifinde gösterilir, onay tarifle gelir):
|
||||
|
||||
| Alan | Örnek |
|
||||
| --- | --- |
|
||||
| Seed artefaktları | Wizard, custom component (visual/code modu), `crud/`, SQL nesneleri (tablo/view/SP/fonksiyon), Custom Endpoint, Dynamic Service, BackgroundWorker, bildirim türü/kuralı, dil anahtarı, yetki kaydı, **SEO kaydı** (§0.9) |
|
||||
| Mevcut bileşeni genişletme | Kullanılan bir `ui` bileşenine **eksik olay / prop / küçük yetenek** ekleme (§7.3 notu) — komponentin %70'i hazır araçlarla kuruluyorsa kalanı bu eklemelerle tamamlanır; `componentProps.json` girdisini tamamlama |
|
||||
| Mevcut sözlüğü genişletme | Yeni EditorScript tarifi (`scriptRecipes.ts` ↔ `Domain.Shared/Editors` birlikte), yeni `EditorOptions` anahtarı, yeni `DefaultValue` token'ı — **geriye dönük uyumlu** olmak şartıyla |
|
||||
| Tasarımcı sözleşmesi | Var olan düğüme prop/varsayılan ekleme, yeni Script Builder tarifi |
|
||||
| Seed artefaktları | Wizard, custom component (visual/code modu — kod veritabanında yaşar, Core değildir), `crud/`, SQL nesneleri (tablo/view/SP/fonksiyon), Custom Endpoint, Dynamic Service, BackgroundWorker, bildirim türü/kuralı, numaratör, rapor şablonu, dil anahtarı, yetki kaydı, **SEO kaydı** (§0.9), modül dokümanı |
|
||||
| Var olan sözleşmeyi kullanma | DTO'da zaten bulunan her `*Json` anahtarı, var olan her `EditorScript` tarifi, `EditorOptions` anahtarı (alan seviyesinde sözlük dışı anahtar dahil — reference §9.8), `DefaultValue` token'ı, tasarımcı düğümü/prop'u/olayı |
|
||||
|
||||
**Çerçeve dışı — önce sor, onay olmadan dokunma:**
|
||||
**Core — yalnızca "core sisteme ekle" komutuyla:**
|
||||
|
||||
| Alan | Örnek |
|
||||
| --- | --- |
|
||||
| Var olan bileşeni genişletme | `ui` bileşenine olay/prop/küçük yetenek, `componentProps.json` / `catalog.ts` (`DESIGNER_PRIMARY_EVENTS`, `NAMED_UNION_OPTIONS`, `PROPERTY_OVERRIDES`) girdisi, tasarımcı düğümüne prop/varsayılan (§7.3 notu) |
|
||||
| Var olan sözlüğü genişletme | Yeni EditorScript / Script Builder tarifi (`scriptRecipes.ts` ↔ `Domain.Shared/Editors`), yeni `EditorOptions` sözlük girdisi ya da preset, yeni `DefaultValue` token'ı, yeni `CustomValueType`/enum değeri |
|
||||
| ListForm sözleşmesi | `ListForm`/`ListFormField` DTO'suna ya da `*Json` kolonuna yeni alan (`GridEditingDto.X` gibi), ListForm editöründe yeni ayar, liste/form runtime'ına yeni davranış (`views/list`, `views/form`) |
|
||||
| Yeni React bileşeni / sayfası | Yeni `ui` bileşeni, yeni toolbox ailesi, `EXCLUDED_COMPONENTS` değişikliği, `views/` altına elle sayfa, Developer Kit menüsüne yeni ekran, var olan bileşeni yeniden yazmak ya da mevcut davranışını değiştirmek |
|
||||
| Çekirdek motor | ListForm runtime, seeder'lar, `codeGenerator.ts`, yetki/kimlik altyapısı, `DataSourceManager`, dispatcher/derleyici (`CustomEndpointAppService`, `DynamicServiceCompiler`) |
|
||||
| Backend şeması | Yeni ABP modülü/entity/migration, platform tablolarında (`{Önek}_{H\|T\|B}_{Ad}` — reference §12.1) kolon değişikliği, `TableNameEnum`/`TableNameResolver` değişikliği, DTO/JSON kolon sözleşmesini **bozan** değişiklik |
|
||||
| Çekirdek motor | ListForm runtime, seeder'lar, `codeGenerator.ts`, yetki/kimlik altyapısı, `DataSourceManager`, dispatcher/derleyici (`CustomEndpointAppService`, `DynamicServiceCompiler`), MCP aracı/prompt'u, wizard deploy |
|
||||
| Backend şeması | Yeni ABP modülü/entity/migration, platform tablolarında (`{Önek}_{H\|T\|B}_{Ad}` — reference §12.1) kolon değişikliği, `TableNameEnum`/`TableNameResolver` değişikliği |
|
||||
| Bağımlılık | Yeni NuGet/npm paketi, sürüm yükseltme |
|
||||
| Sabit yapılar | `data/App.Menus.Routes.json` satırlarının eklenmesi/silinmesi/yolunun değişmesi (`Seo*` alanları hariç, §0.9), `PlatformConsts` içindeki mevcut değerlerin değişmesi |
|
||||
| Dış dünya | Yeni harici entegrasyon, yeni bağlantı tipi, üçüncü taraf servis |
|
||||
|
||||
**Sorma biçimi:** çerçeve içinde yapılabilen her şeyi **önce bitir**, sonra tek soruda
|
||||
`AskUserQuestion` ile sor — neden konfigürasyon/seed yolu yetmiyor (bir iki cümle), en küçük
|
||||
hangi değişiklik yeter, hangi dosyalara dokunacak, geri alma nasıl olacak. Seçenekler arasında
|
||||
daima "çerçeve içinde daraltılmış çözüm" alternatifi de bulunsun. Onay gelmeden `api/` ya da
|
||||
`ui/` altında çerçeve dışı bir satır yazılmaz; onay bir talebe özeldir, sonraki talebe taşınmaz.
|
||||
**Core sayılmayan kod işi:** kullanıcının bildirdiği bir hatanın düzeltilmesi (var olan davranışı
|
||||
belgelendiği hâline getirmek — yeni ayar, alan ya da seçenek eklemeden), kullanıcının dosya/sınıf
|
||||
adıyla istediği kod değişikliği, refactor/temizlik isteği, doküman. Düzeltme sırasında "şu ayar da
|
||||
olsa iyi olur" denen her şey yeni özelliktir ve komut bekler.
|
||||
|
||||
**Komut yoksa:** çerçeve içinde yapılabilen her şeyi bitir, Core'a dokunma; son mesajda tek bir
|
||||
**"Core gerektiren kısım"** notu yaz — eksik yetenek, envanterde denenip yetmeyen yollar (bir iki
|
||||
cümle), en küçük Core değişikliği ve dokunacağı dosyalar, geri alma. Soru kutusuyla Core seçeneği
|
||||
sunulmaz, varsayılan seçenek Core olmaz; karar kullanıcının komutudur. MCP/talep döngüsünde
|
||||
(§0.11–§0.12) analizdeki `(onay)` kararı Core komutu değildir: Core ihtiyacı analize ve üretim
|
||||
notuna yazılır, üretim çerçeve içinde kalır.
|
||||
|
||||
**Komut gelince:** yalnızca komutta adı geçen değişiklik yapılır; komut sonraki talebe taşınmaz,
|
||||
kapsamı genişletmez. Core'a eklenen her özellik aynı işte `lowcode-reference.instructions.md`
|
||||
envanterine (ve ilgiliyse bu dosyaya) yazılır — envanterde olmayan yetenek bir sonraki talepte
|
||||
yeniden Core'a gider.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -653,8 +679,9 @@ değildir) ve içindeki satırları taşır; satırlar demo veridir (§0.10.1).
|
|||
**Kurallar**
|
||||
- **Onaylanmış analiz tarifin kendisidir; üretim karar vermez.** Soru sorulmaz, seçim yapılmaz,
|
||||
analizin yazdığı hiçbir şey değiştirilmez ya da daraltılmaz — tek istisna platform kuralıyla çelişen kısımdır (aşağıda). Bu dosyadaki "kullanıcıya sor"
|
||||
kuralları (onaycı, görselden okunamayan zorunlu alan, çerçeve dışı ihtiyaç) bu döngüde analizin
|
||||
**(onay)** kararlarıyla çözülmüştür. Analizde karşılığı olmayan küçük bir ayrıntı (§0.6
|
||||
kuralları (onaycı, görselden okunamayan zorunlu alan) bu döngüde analizin **(onay)**
|
||||
kararlarıyla çözülmüştür; Core ihtiyacı bunun dışındadır — `(onay)` Core komutu sayılmaz (§0.8).
|
||||
Analizde karşılığı olmayan küçük bir ayrıntı (§0.6
|
||||
varsayılanı olan türden) varsayılanla tamamlanır ve sonuç notuna yazılır.
|
||||
- **Platform kuralı analizden önce gelir.** Analiz, bu dosyadaki bağlayıcı bir kuralla çelişiyorsa
|
||||
(görsel kolonu `nvarchar(MAX)` + `dxImageUpload`, tanım tablosunda `IsActive`, parametreli SQL,
|
||||
|
|
@ -1024,7 +1051,8 @@ Query'de üretilmez (kaynak tablo adı değildir), gerekiyorsa elle yazılır.
|
|||
`1` Toolbar (§4.9)
|
||||
|
||||
**`ValidationRule.Type`** (`UiColumnValidationRuleTypeEnum`) — seed'e **metin** olarak yazılır:
|
||||
`required` `numeric` `range` `stringLength` `custom` `compare` `pattern` `email` `async` (§4.3.6)
|
||||
`required` (1) `numeric` (2) `range` (3) `stringLength` (4) `custom` (5) `compare` (6) `pattern` (7)
|
||||
`email` (8) `async` (9) (§4.3.6). `compare` `ComparisonTarget`, `custom`/`async` `ValidationCallback` ister.
|
||||
|
||||
**`WorkerType`** (`WorkerTypeEnum`) — `1` MailQueueWorker · `2` SqlWorker ·
|
||||
`3` NotificationWorker · `4` SessionCleanupWorker · `5` BackupWorker · `6` ProbationReminderWorker (§9.10)
|
||||
|
|
@ -1053,14 +1081,22 @@ yazılır:
|
|||
| `DefaultLayout` | `grid` · `card` · `pivot` · `chart` · `tree` · `gantt` · `scheduler` · `todo` (küçük harf) |
|
||||
| Bildirim kanalı (`NotificationChannels`) | `Mail` · `Sms` · `WhatsApp` · `Telegram` · `Rocket` · `Desktop` · `UiToast` · `UiActivity` — etiketleri `App.NotificationChannel.{Kanal}` dil anahtarlarıdır |
|
||||
| Bildirim alıcı tipi (`NotificationRecipientTypes`) | `User` · `Role` · `OrganizationUnit` · `All` · `Custom` |
|
||||
| Pivot `Area` | `row` · `column` · `data` · `filter` |
|
||||
| Pivot `GroupInterval` | `""` (yok) · `day` · `dayOfWeek` · `month` · `quarter` · `year` |
|
||||
| Stil `RowType` | `data` · `detail` · `detailAdaptive` · `filter` · `group` · `groupFooter` · `header` · `totalFooter` |
|
||||
| `CascadeFilterOperator` | `=` · `<>` · `<` · `<=` · `>` · `>=` · `contains` · `notcontains` · `startswith` · `endswith` · `isblank` · `isnotblank` · `between` |
|
||||
| `JoinType` | `INNER JOIN` · `LEFT JOIN` · `RIGHT JOIN` |
|
||||
| `FixedPosition` · `SortDirection` | `left` · `right` · `asc` · `desc` |
|
||||
|
||||
**`DbSourceType` / `KeyFieldDbSourceType`** (`System.Data.DbType`):
|
||||
|
||||
| # | Ad | SQL karşılığı |
|
||||
| --- | --- | --- |
|
||||
| 0 | AnsiString | `varchar` (entity varsayılanı; wizard `16` yazar) |
|
||||
| 1 | Binary | `binary`, `varbinary`, `image` |
|
||||
| 2 | Byte | `tinyint` |
|
||||
| 3 | Boolean | `bit` |
|
||||
| 4 | Currency | `money` |
|
||||
| 5 | Date | `date` |
|
||||
| 6 | DateTime | `datetime`, `datetime2`, `smalldatetime` |
|
||||
| 7 | Decimal | `decimal`, `numeric`, `money` |
|
||||
|
|
@ -1069,11 +1105,20 @@ yazılır:
|
|||
| 10 | Int16 | `smallint` |
|
||||
| 11 | Int32 | `int` |
|
||||
| 12 | Int64 | `bigint` |
|
||||
| 13 | Object | `sql_variant` |
|
||||
| 14 · 15 | SByte · Single | — · `real` |
|
||||
| 16 | String | `nvarchar`, `varchar`, `nchar`, `char`, `text` |
|
||||
| 17 | Time | `time` |
|
||||
| 18 · 19 · 20 | UInt16 · UInt32 · UInt64 | — |
|
||||
| 21 | VarNumeric | — |
|
||||
| 22 · 23 | AnsiStringFixedLength · StringFixedLength | `char` · `nchar` |
|
||||
| 25 | Xml | `xml` |
|
||||
| 26 | DateTime2 | `datetime2` |
|
||||
| 27 | DateTimeOffset | `datetimeoffset` |
|
||||
|
||||
İstemci tipi bu sayıdan türetilir (reference §9.7 `SourceDbType`): Byte, SByte, Binary, Time, Xml ve
|
||||
VarNumeric boş tip verir; `tinyint` kolonunda sayı filtresi/biçimi için `10` Int16 yaz.
|
||||
|
||||
**Editör tipleri (`EditorType2`)** — 22 tip, alana **metin** olarak yazılır. DevExtreme'den
|
||||
gelenler: `dxAutocomplete`, `dxCalendar`, `dxCheckBox`, `dxColorBox`, `dxDateBox`,
|
||||
`dxDateRangeBox`, `dxDropDownBox`, `dxHtmlEditor`, `dxLookup`, `dxNumberBox`, `dxRadioGroup`,
|
||||
|
|
@ -1083,7 +1128,7 @@ Platformun kendi editörleri (`PlatformEditorTypes`): `dxGridBox`, `dxImageViewe
|
|||
|
||||
> **Tuzak:** `PlatformConsts.EditorTypes.dxLookup` sabiti bozuk bir metin taşır
|
||||
> (`"dxHtmlEdidxLookuptor"`). Hiçbir yerde kullanılmadığı için etkisi yoktur, ama C# seeder
|
||||
> yazarken bu sabiti kullanma; `EditorType2 = "dxLookup"` diye düz metin yaz. Diğer 20 sabit
|
||||
> yazarken bu sabiti kullanma; `EditorType2 = "dxLookup"` diye düz metin yaz. Diğer 21 sabit
|
||||
> doğrudur.
|
||||
|
||||
Tip seçimi kuralı: `Boolean → dxCheckBox`/`dxSwitch`, tarih → `dxDateBox`, sayı → `dxNumberBox`,
|
||||
|
|
@ -1351,9 +1396,11 @@ Her `Items` öğesi:
|
|||
| `IsRequired` | `[Fields]` Zorunluluk (`ValidationRuleDto`). |
|
||||
| `IncludeInEditingForm` | `[Fields]` `false` ise yalnızca grid sütunu olur, forma girmez (`EditGroupOrderNo`). |
|
||||
| `ColSpan` | `[Fields]` Formda kaç kolon kaplar (grubun `ColCount` değeri içinde). |
|
||||
| `LookupDataSourceType` | `[Fields]` `1/2/3` — bkz. §3. `0` = lookup yok. |
|
||||
| `LookupDataSourceType` | `[Fields]` `1/2/3` — bkz. §3. Lookup yalnızca `LookupQuery` doluysa üretilir; wizard ekranı tipi `1` ile açar. |
|
||||
| `LookupQuery` | `[Fields]` `Query` tipinde SQL; `StaticData` tipinde JSON dizisi; `WebService` tipinde URL. |
|
||||
| `ValueExpr` / `DisplayExpr` | `[Fields]` Lookup'ın değer ve etiket kolonları. |
|
||||
| `ValueExpr` / `DisplayExpr` | `[Fields]` Lookup'ın değer ve etiket kolonları (açıkça `null` verilirse `null` yazılır). |
|
||||
| `DefaultValue` | `[Fields]` Yeni kayıt varsayılanı; `FormFieldsDefaultValueJson`'a `CustomValueType: 1` olarak yazılır (§4.3.5.1). |
|
||||
| `CascadeParentFields` · `CascadeRelationField` · `CascadeFilterOperator` · `CascadeEmptyFields` | `[Fields]` Bağımlı liste (§4.3.4). Wizard ekranında `DefaultValue` ve `Cascade*` için giriş yoktur; MCP/seed girdisiyle gelir, düzenlemede korunur. |
|
||||
|
||||
### 4.3.1 Sütunlar nasıl otomatik üretilir
|
||||
|
||||
|
|
@ -1509,16 +1556,20 @@ başlangıçlar bu anahtarların doğru bileşimlerini üretir.
|
|||
Wizard'daki `LookupDataSourceType` + `LookupQuery` + `ValueExpr` + `DisplayExpr` alanları alanın
|
||||
`LookupJson` kolonuna dönüşür. **Cascade de wizard girdisidir:** öğedeki `CascadeParentFields`,
|
||||
`CascadeRelationField`, `CascadeFilterOperator`, `CascadeEmptyFields` aynı adla `LookupJson`'a
|
||||
yazılır (`WizardConsts.DefaultLookupJson`; yalnızca dolu olanlar). Wizard ekranında bu alanların
|
||||
yazılır (`WizardConsts.DefaultLookupJson`): `CascadeParentFields` ve `CascadeEmptyFields` doluysa yazılır;
|
||||
`CascadeRelationField` ile `CascadeFilterOperator` yalnızca `CascadeParentFields` doluysa yazılır ve
|
||||
operatör boşsa da `"="` olarak yazılır. `LookupJson` yalnızca `LookupQuery` doluysa üretilir — lookup'ı
|
||||
olmayan bir ebeveyn alana wizard girdisiyle `CascadeEmptyFields` yazılamaz; böyle bir alanın `LookupJson`'ı
|
||||
`ListForm`/`Fields` katmanında elle verilir (§4.4). Wizard ekranında bu alanların
|
||||
adımı yoktur, düzenlemede korunur. MCP `deploy_wizard` ile cascade'li ekran doğrudan üretilir;
|
||||
cascade eksik yetenek değildir ve analizde `Ready to Start`'ı engellemez. Tam sözleşme:
|
||||
|
||||
| Alan | Anlam |
|
||||
| --- | --- |
|
||||
| `DataSourceType` | `1` StaticData · `2` Query · `3` WebService |
|
||||
| `ValueExpr` / `DisplayExpr` | Varsayılan `Key` / `Name` |
|
||||
| `ValueExpr` / `DisplayExpr` | Varsayılan `Key` / `Name` (`LookupDto`); wizard'ın ürettiği `DefaultLookupJson` küçük harfli `key` / `name` yazar. Query cevabındaki `Key`/`Name`/`Group` kolonları istemcide `key`/`name`/`group`'a eşlenir |
|
||||
| `LookupQuery` | Kaynağın kendisi (tipe göre biçim değişir, aşağıda) |
|
||||
| `CascadeParentFields` | **Çocuk alanda** doldurulur; değerleri sorguya taşınacak ebeveyn alan(lar), virgülle. Sırayla `@param0`, `@param1`… olur (`Query`/`WebService`); boş ya da gelmeyen ebeveyn `NULL` bağlanır. Ebeveyn çocuğu, değeri boşken kilitler (bool ebeveynde `false` da boştur) ve değiştiğinde temizler; ebeveyn yalnızca gerçekten süzülen liste için yazılır, hesap için kullanılmaz. Değer her zaman **metin** parametre olarak bağlanır (`ListFormSelectAppService.ToLookupParameter`), sayı anahtarlı ebeveyn de çalışır; dönüşümü kolon tipine göre veritabanı yapar. `WebService` gövdesine değer JSON kaçışlı yazılır |
|
||||
| `CascadeParentFields` | **Çocuk alanda** doldurulur; değerleri sorguya taşınacak ebeveyn alan(lar), virgülle. Sırayla `@param0`, `@param1`… olur (`Query`/`WebService`); boş ya da gelmeyen ebeveyn `NULL` bağlanır. Ebeveyn çocuğu, değeri boşken kilitler (`!value`: bool ebeveynde `false`, sayı ebeveynde `0` da boştur) ve değiştiğinde temizler; ebeveyn yalnızca gerçekten süzülen liste için yazılır, hesap için kullanılmaz. Değer her zaman **metin** parametre olarak bağlanır (`ListFormSelectAppService.ToLookupParameter`), sayı anahtarlı ebeveyn de çalışır; dönüşümü kolon tipine göre veritabanı yapar. `WebService` gövdesine değer JSON kaçışlı yazılır |
|
||||
| `CascadeRelationField` | **Çocuk alanda**, yalnızca `StaticData`'da anlamlıdır: öğede ilk ebeveynin değeriyle karşılaştırılan alan; boşsa `group`. Ebeveyn boşken liste süzülmez |
|
||||
| `CascadeFilterOperator` | `StaticData` cascade filtresinin operatörü; varsayılan `=` |
|
||||
| `CascadeEmptyFields` | **Ebeveyn alanda** doldurulur; bu alan değişince boşaltılacak çocuk alanlar, virgülle. Ara halka (İl) hem çocuk hem ebeveyn olduğu için iki tarafı birden taşır |
|
||||
|
|
@ -1554,7 +1605,7 @@ Adres zincirinin hazır örneği Kiracılar ekranıdır: Ülke › İl › İlç
|
|||
| --- | --- | --- |
|
||||
| `1` StaticData | `[{"key":"Wares","name":"App.StaticLookup.Wares"},{"key":"Service","name":"App.StaticLookup.Service"}]` | `name` **her zaman dil anahtarıdır** (§4.3.4.1), düz metin yazılmaz. Kolon **sayı** tipindeyse `key` sayı, **metin** tipindeyse `key` metin olmalıdır; aksi hâlde seçim eşleşmez. Cascade gerekiyorsa her öğeye `group` eklenir. |
|
||||
| `2` Query | `SELECT Id AS [Key], Name AS [Name] FROM ... WHERE IsDeleted = 0` | Cascade'de ebeveyn değerleri `@param0…` ile gelir; boş ebeveyn tüm listeyi göstersin diye `(Kolon = @param0 OR @param0 IS NULL)` kalıbı kullanılır. Sorgu ekranın veri kaynağında/tenant bağlamında çalışır, `@USERID` gibi token'lar çözülür. |
|
||||
| `3` WebService | `METHOD;url;bodyJson;keySelector;nameSelector;groupSelector` | Noktalı virgülle **altı parça**. Selector'lar her satır `a` üzerinde çalışan JS ifadeleridir (`a.id`, `a.name`, `null`). Gövdedeki `@param0`, `@param1`… cascade filtre değerleriyle doldurulur. Örnek: `GET;notification-rule/notification-types;{};a.id;a.name;null` |
|
||||
| `3` WebService | `METHOD;url;bodyJson;keySelector;nameSelector;groupSelector` | Noktalı virgülle **altı parça**. Selector'lar her satır `a` üzerinde çalışan JS ifadeleridir (`a.id`, `a.name`, `null`). Gövdedeki `@param0`, `@param1`… cascade filtre değerleriyle doldurulur. Örnek: `GET;notification-rule/notification-types;{};a.id;a.name;null`. Eksik ya da boş seçici `a.id` / `a.name` / `a.group`'a düşer; seçici ifade (`a.id`) ya da ok fonksiyonu (`a => a.id`) olabilir. Store anahtarı `valueExpr`'in küçük harflisidir; boş ebeveyn gövdeye `null` metni olarak yazılır (tırnak içindeyse `"null"`) |
|
||||
|
||||
Cascade örneği — Ülke → İl → İlçe (aşağıdaki nesneler `LookupJson` kolonuna **tek satır,
|
||||
kaçışlanmış JSON string** olarak yazılır; canlı örnek Tenants ekranı, `LookupQueryValues.CityValues`
|
||||
|
|
@ -1626,7 +1677,8 @@ alanında vermektir; o anahtara deploy dokunmaz.
|
|||
### 4.3.5 Varsayılan değerler — `*FieldsDefaultValueJson`
|
||||
|
||||
Kullanıcının doldurmayacağı alanlar (audit, tenant, durum, **belge numarası**) script ile değil,
|
||||
bu JSON'larla doldurulur. Dört ayrı liste vardır ve hepsi aynı öğe şeklini taşır:
|
||||
bu JSON'larla doldurulur. Dört etkin liste vardır ve hepsi aynı öğe şeklini taşır (aynı
|
||||
`FieldName` iki kez verilirse sonraki geçerlidir):
|
||||
|
||||
| Kolon | Ne zaman çalışır |
|
||||
| --- | --- |
|
||||
|
|
@ -1635,6 +1687,10 @@ bu JSON'larla doldurulur. Dört ayrı liste vardır ve hepsi aynı öğe şeklin
|
|||
| `DeleteFieldsDefaultValueJson` | Delete (soft delete alanları) |
|
||||
| `FormFieldsDefaultValueJson` | Form açılışı (Select) — ekrana gelen varsayılanlar |
|
||||
|
||||
Beşinci kolon `SelectFieldsDefaultValueJson` ListForm editöründe (Veritabanı › Select) düzenlenebilir ama
|
||||
`DefaultValueManager` onu **okumaz** — Select işlemi de `FormFieldsDefaultValueJson`'ı kullanır. Okuma
|
||||
sorgusuna kullanıcı/kiracı koşulu gerekiyorsa `DefaultFilter`'a token'la yaz (`"CreatorId" = '@USERID'`).
|
||||
|
||||
```jsonc
|
||||
[
|
||||
{ "FieldName": "Id", "FieldDbType": 9, "Value": "@NEWID", "CustomValueType": 2 },
|
||||
|
|
@ -1651,14 +1707,14 @@ bu JSON'larla doldurulur. Dört ayrı liste vardır ve hepsi aynı öğe şeklin
|
|||
|
||||
| # | Tip | `Value` ne demek |
|
||||
| --- | --- | --- |
|
||||
| 1 | `Value` | Sabit değer (`false`, `3`, `Taslak`, `GETDATE()`) |
|
||||
| 1 | `Value` | Sabit değer (`false`, `3`, `Taslak`). SQL değil **parametredir**: `GETDATE()` gibi ifade tarih kolonunda parse edilemez ve alan **NULL** yazılır — şimdiki zaman için `CustomKey` `@NOW` |
|
||||
| 2 | `CustomKey` | Aşağıdaki token'lardan biri |
|
||||
| 3 | `DbQuery` | Değer `SqlQuery` alanındaki **tek hücre** döndüren sorgudan gelir (ekranın `DataSourceCode`/tenant bağlamında çalışır) |
|
||||
| 4 | `QueryParams` | Değer, adresteki query string parametresinden okunur; `Value` parametre adıdır |
|
||||
| 3 | `DbQuery` | Değer `SqlQuery` alanındaki **tek hücre** döndüren sorgudan gelir (ekranın `DataSourceCode`/tenant bağlamında çalışır); sorgudaki `@USERID`, `@TENANTID` gibi token'lar `DefaultValueHelper` ile önceden çözülür |
|
||||
| 4 | `QueryParams` | Değer, adresteki query string parametresinden okunur; `Value` parametre adıdır, değer `FieldDbType`'a göre biçimlenir |
|
||||
| 5 | `Sequence` | `Value` bir **Sequence adıdır** (§9.9); yazma anında sıradaki numara alınır, form açılışında (Select) yalnızca ad döner ve UI numarayı ayrıca ister |
|
||||
|
||||
**`CustomKey` token'ları** (`PlatformConsts.DefaultValues`) — `DefaultValueManager`'ın tanıdığı
|
||||
tam küme:
|
||||
**`CustomKey` token'ları** (`PlatformConsts.DefaultValues`, `@AUTONUMBER` hariç — o yalnız istemcide,
|
||||
`Value` tipiyle çalışır) — `DefaultValueManager`'ın tanıdığı tam küme:
|
||||
|
||||
| Token | Değer |
|
||||
| --- | --- |
|
||||
|
|
@ -1670,8 +1726,9 @@ tam küme:
|
|||
| `@SELECTED_IDS` | Seçili anahtarların tamamı (her operasyonda) |
|
||||
| `@TENANTID` | Aktif kiracı |
|
||||
|
||||
Listedeki tokenlar dışında bir `CustomKey` değeri **`null` üretir** ve o alan yazılmaz. Bu
|
||||
yüzden `@AUTONUMBER`, `CustomKey` değil **`CustomValueType: 1` (Value)** ile yazılır:
|
||||
Listedeki token'lar dışında `@{AlanAdı}` yazılırsa Insert/Update'te gönderilen kaydın o alanının değeri
|
||||
kopyalanır (alan seviyesinde `C`/`U` yetkisi gerekir); başka her değer `null` üretir ve alan yazılmaz.
|
||||
Bu yüzden `@AUTONUMBER`, `CustomKey` değil **`CustomValueType: 1` (Value)** ile yazılır:
|
||||
|
||||
```jsonc
|
||||
{ "FieldName": "SiraNo", "FieldDbType": 11, "Value": "@AUTONUMBER", "CustomValueType": 1 }
|
||||
|
|
@ -1739,6 +1796,8 @@ da forma yazılmaz. Numara/kod alanı otomatik değilse (kullanıcı girer) kura
|
|||
3. `@AUTONUMBER`, `DbQuery` ile `MAX(...) + 1`, sabit metin ya da `InsertAfterCommand` ile numara
|
||||
üretme yazılmaz. Tek istisna talebin açıkça boşluksuz numara istemesidir (§9.9 son paragraf);
|
||||
o zaman karar analizde **(onay)** ile yazılır.
|
||||
Belgeyi formdan değil bir yordam açıyorsa (teklif talebinin alternatif kopyası, tekliften
|
||||
dönüşen sipariş) numara yine aynı numaratörden `Adm_P_SequenceNext` ile alınır (§9.9).
|
||||
4. Analiz numaratörü madde 8'de (alan → numaratör adı, `Prefix`, `FormatTemplate`, `ResetPeriod`)
|
||||
gösterir; talepte biçim yoksa varsayılan `{Prefix}{Number}{Suffix}`, `PaddingSize: 5`, `ResetPeriod: 0`
|
||||
ve modül kısaltmasından `Prefix` kararı madde 9'a yazılır.
|
||||
|
|
@ -1759,6 +1818,11 @@ kuralı kayıttan önce istemcide denetlenir (`getTemplateEditorRequiredErrors`)
|
|||
iptal edilip popup açık kalır. Bu editörlerde yalnızca `required` çalışır; diğer kural tipleri
|
||||
gerekiyorsa sunucu tarafı kontrol yazılır.
|
||||
|
||||
Kurallar liste popup'ı ve form sayfası için aynı yardımcıdan (`list/shared/validationRules.ts`) üretilir.
|
||||
`Message` dil anahtarıdır ve çevrilir; boş bırakılırsa DevExtreme'in yerelleştirilmiş varsayılanı çıkar.
|
||||
Form sayfasında zorunluluk `isRequired` ile işaretlenir, `Message`'ı olan `required` kuralı ayrıca item'a
|
||||
geçer. Doğrulama istemcidedir; iş kuralı zorunluysa sunucu tarafında da uygulanır.
|
||||
|
||||
| `Type` | Kullanılan alanlar |
|
||||
| --- | --- |
|
||||
| `required` | `Message`, `Trim` |
|
||||
|
|
@ -1767,9 +1831,9 @@ gerekiyorsa sunucu tarafı kontrol yazılır.
|
|||
| `stringLength` | `Min`, `Max`, `Trim` |
|
||||
| `pattern` | `Pattern` (regex) |
|
||||
| `email` | `Message`, `IgnoreEmptyValue` |
|
||||
| `compare` | `ComparisonType` (`==`, `===`, `!=`, `!==`, `<`, `<=`, `>`, `>=`) |
|
||||
| `custom` | JS ile doğrulama; `Reevaluate` |
|
||||
| `async` | Sunucuya sorarak doğrulama; `Reevaluate` |
|
||||
| `compare` | `ComparisonTarget` (aynı kayıttaki alan adı), `ComparisonType` (`==`, `===`, `!=`, `!==`, `<`, `<=`, `>`, `>=`; boşsa `==`) — "Bitiş ≥ Başlangıç": `{Type:"compare", ComparisonTarget:"StartDate", ComparisonType:">="}` |
|
||||
| `custom` | `ValidationCallback`: `eval` edilen JS fonksiyonu, `true` geçerlidir — `"(e) => e.value > 0"`; `e.data` kaydın tamamıdır. `Reevaluate` |
|
||||
| `async` | `ValidationCallback` Promise dönebilir (`"(e) => fetch(...).then(r => r.ok)"`); `Reevaluate`. Derlenemeyen ya da hata veren fonksiyon kuralı geçmiş sayar |
|
||||
|
||||
```jsonc
|
||||
"ValidationRuleJson": "[{\"Type\":\"required\",\"Message\":\"App.Validation.Required\"},
|
||||
|
|
@ -1783,20 +1847,22 @@ script gerekmez.
|
|||
|
||||
| Alan | Anlam |
|
||||
| --- | --- |
|
||||
| `RowType` | `data` (varsayılan) · `group` · `header` · `filter` · `detail` · `groupFooter` · `totalFooter` |
|
||||
| `RowType` | `data` (varsayılan) · `group` · `header` · `filter` · `detail` · `detailAdaptive` · `groupFooter` · `totalFooter`. Koşul yalnızca `data` satırında değerlendirilir; diğer satır tiplerinde stil koşulsuz uygulanır |
|
||||
| `UseRow` | `true` ise stil hücreye değil **tüm satıra** uygulanır |
|
||||
| `Condition` | `=`, `<>`, `<`, `<=`, `>`, `>=`, `contains`, `notcontains`, `startswith`, `endswith`, `isblank`, `isnotblank`, `between`, `anyof`, `noneof` |
|
||||
| `ConditionValue` | Boş bırakılırsa koşul aranmaz, stil her zaman uygulanır |
|
||||
| `Condition` | `=`, `<>`, `<`, `<=`, `>`, `>=`, `contains`, `notcontains`, `startswith`, `endswith`, `isblank`, `isnotblank`, `anyof`, `noneof`. Karşılaştırma gevşektir (`==`). `between`'de `ConditionValue` `[min, max]` dizisidir (`[10, 20]`, uçlar dahil). Yönetim formu yalnızca bu operatörleri sunar |
|
||||
| `ConditionValue` | Boş bırakılırsa koşul aranmaz, stil her zaman uygulanır; `isblank`/`isnotblank` değer istemez. `anyof`/`noneof`'ta JSON dizi metni: `["A","B"]` |
|
||||
| `CssStyles` | `anahtar:değer` çiftleri, aralarında `|`: `background-color:#fee | font-weight:bold` |
|
||||
| `CssClassName` | Hazır bir CSS sınıfı kullanılacaksa |
|
||||
|
||||
Alan üzerindeki `ColumnCssClass` / `ColumnCssValue` kolonları da aynı işi koşulsuz yapar.
|
||||
Stil Grid, Tree ve Pivot'ta uygulanır, Card'da uygulanmaz. Alan üzerindeki `ColumnCssClass` /
|
||||
`ColumnCssValue` kolonları da aynı işi koşulsuz yapar.
|
||||
|
||||
### 4.3.8 Ekran üstü ek filtre — `ExtraFilterJson`
|
||||
|
||||
Grid'in üstünde duran, kullanıcının seçtiği değere göre listeyi süzen filtre çubuğu
|
||||
(tarih aralığı, şube, durum). Filtre satırından (`FilterRowJson`) farkı: her zaman görünür,
|
||||
varsayılan değeri olur ve **yeni kayıtta o alanı otomatik doldurur**.
|
||||
varsayılan değeri olur. Grid, Tree ve Card'da çizilir (Gantt, Scheduler, Todo, Pivot, Chart'ta yok);
|
||||
`Caption` **çevrilmez**, düz metin basılır.
|
||||
|
||||
```jsonc
|
||||
[
|
||||
|
|
@ -1814,8 +1880,9 @@ varsayılan değeri olur ve **yeni kayıtta o alanı otomatik doldurur**.
|
|||
- Seçilen değerler `[FieldName, Operator, Value]` üçlüsüne çevrilir, URL'deki `filter` parametresiyle
|
||||
`and` ile birleştirilir. Böylece filtreli ekran adresi paylaşılabilir.
|
||||
- `DefaultValue` dolu ise seçim temizlenemez ve liste ilk açılışta o değerle gelir.
|
||||
- Ek filtre ile yönetilen alan, yeni kayıt varsayılanlarında **atlanır** (§4.3.5) — değeri
|
||||
filtreden gelir.
|
||||
- Ek filtre ile yönetilen alan yeni kayıtta **atlanır**: ne `DefaultValue` ne URL değeri uygulanır,
|
||||
alan boş açılır. Yeni kayıtta dolu gelmesi gerekiyorsa `FormFieldsDefaultValueJson` ya da
|
||||
`?filter=` adresi kullanılır (reference §5.8).
|
||||
### 4.4 Çalışan örnek — wizard cevabı (deploy girdisi)
|
||||
|
||||
Aşağıdaki **düz** biçim wizard ekranının POST ettiği ve MCP `deploy_wizard`'ın aldığı cevaptır
|
||||
|
|
@ -2155,7 +2222,7 @@ Wizard Manager'daki talep silmesini kullanır.
|
|||
"TabType": "List", // List|Card|Tree|Gantt|Scheduler|Todo|Form|Chart|Pivot
|
||||
"TabTitle": "App.Mrp.OrderItems", // dil anahtarı
|
||||
"Code": "App.Mrp.OrderItems", // hedef ListFormCode
|
||||
"IsRefresh": false, // ana kayıt değişince yenilensin; MCP yeni bağlantıda false yazar
|
||||
"IsRefresh": false, // true: alt sekmede yazınca ana kayıt yeniden çekilir; MCP yeni bağlantıda false yazar
|
||||
"Relation": [
|
||||
{ "ParentFieldName": "Id", "ChildFieldName": "OrderId", "DbType": 11 }
|
||||
]
|
||||
|
|
@ -2163,7 +2230,10 @@ Wizard Manager'daki talep silmesini kullanır.
|
|||
]
|
||||
```
|
||||
|
||||
`Relation` bir dizidir — bileşik anahtarda birden fazla eşleme verilir.
|
||||
`Relation` bir dizidir ama istemci yalnızca değeri dolu **ilk** eşlemeyi kullanır — bileşik anahtar
|
||||
desteklenmez. `Form` sekmesi kaydı ilişki alanıyla (`ChildFieldName = ana alan değeri`) yükler, yeni kayıtta
|
||||
ilişki alanını doldurup kilitler; `Chart` sekmesi ana ekranın grafiğini ilişkisiz çizer (reference §5.2). Sekmelerin liste sayfasında,
|
||||
seçili satıra bağlı çizilmesi için ana ekranda `SubFormsListFormType: "List"` (reference §5.6).
|
||||
|
||||
**Alt form ekranının kuralları** (sekmede açılan hedef ekran; MCP ile üretimde de geçerli):
|
||||
|
||||
|
|
@ -2208,10 +2278,10 @@ widget, sorgunun döndürdüğü **her satır için bir kart** çizer:
|
|||
"Color": "Renk",
|
||||
"Icon": "Ikon",
|
||||
"SubTitle": "", // karşılığı olan kolon yoksa boş bırak
|
||||
"OnClick": "", // tıklanınca açılacak adresi taşıyan kolonun adı
|
||||
"OnClick": "", // değeri JS olarak eval edilen kolonun adı ('window.open(''/admin/list/X'')' AS Tikla)
|
||||
"ValueClassName": "text-3xl",
|
||||
"ColSpan": 1,
|
||||
"ColGap": 16,
|
||||
"ColGap": 3,
|
||||
"ClassName": "",
|
||||
"IsActive": true
|
||||
}
|
||||
|
|
@ -2308,16 +2378,14 @@ bu dördü dışında akış kolonu açılmaz:
|
|||
- Dört alan popup düzenleme formuna konmaz (`EditGroupOrderNo`/`EditOrderNo` boş, ayrı "Onay" grubu
|
||||
açılmaz); listede kolon olarak görünür (`Visible: true`).
|
||||
|
||||
| Alan | Tabloda karşılığı |
|
||||
|
||||
| Alan | Tabloda karşılığı |
|
||||
| --- | --- |
|
||||
| `ApprovalUserFieldName` | Onaylayan kullanıcı |
|
||||
| `ApprovalDateFieldName` | Onay tarihi |
|
||||
| `ApprovalStatusFieldName` | Durum |
|
||||
| `ApprovalDescriptionFieldName` | Onay/ret açıklaması |
|
||||
| `ApprovalIsFilterUserName` | Liste yalnızca kullanıcının onayına düşenleri göstersin |
|
||||
| `ApprovalIsResetWorkflow` | Kayıt güncellenince akış başa dönsün. `ApprovalIsManualStart` açıksa sıfırlama akışı yeniden çalıştırmaz; kayıt taslağa döner ve akış başlat düğmesiyle başlar |
|
||||
| `ApprovalIsFilterUserName` | Liste yalnızca kullanıcının onayına düşenleri göstersin: onaycı kolonu **boş** olan (akış başlatılabilsin diye) ya da `\|` ile bölünmüş değerlerinde kullanıcının UserName/Email/Name'i geçen satırlar |
|
||||
| `ApprovalIsResetWorkflow` | Toolbar'daki **Workflow Reset** düğmesini açar (yalnızca akışı başlamış satırda etkin); otomatik sıfırlama yoktur, bayrak kapalıyken `…/reset` reddedilir. `ApprovalIsManualStart` açıksa sıfırlama akışı yeniden çalıştırmaz; kayıt taslağa döner ve akış başlat düğmesiyle başlar |
|
||||
| `ApprovalIsManualStart` | Yeni kayıt akışı kendiliğinden başlatmasın; kayıt taslak kalır, akış toolbar'daki başlat düğmesiyle başlar. Onaya gönderilmiş başlığa satır eklemeyi engelleyen alt formu olan ekranlarda (talep + satırlar) açılır; kapalıyken Grid/Tree yeni kaydın ardından akışı başlatır |
|
||||
|
||||
`Criteria` düğüm grafiğidir. `Kind` değerleri: **`Start`**, **`Compare`**, **`Approval`**,
|
||||
|
|
@ -2346,15 +2414,15 @@ bu dördü dışında akış kolonu açılmaz:
|
|||
"PositionX": 40, "PositionY": 160 },
|
||||
|
||||
{ "Id": "N3", "Kind": "Approval", "Title": "Genel Müdür onayı",
|
||||
"Approver": "<roleOrUserId>", "NextOnApprove": "N5", "NextOnReject": "N6",
|
||||
"Approver": "<userName|email>", "NextOnApprove": "N5", "NextOnReject": "N6",
|
||||
"PositionX": 300, "PositionY": 260 },
|
||||
|
||||
{ "Id": "N4", "Kind": "Approval", "Title": "Yönetici onayı",
|
||||
"Approver": "<roleOrUserId>", "NextOnApprove": "N5", "NextOnReject": "N6",
|
||||
"Approver": "<userName|email>", "NextOnApprove": "N5", "NextOnReject": "N6",
|
||||
"PositionX": 40, "PositionY": 260 },
|
||||
|
||||
{ "Id": "N5", "Kind": "Inform", "Title": "Talep sahibine bilgi",
|
||||
"Approver": "<roleOrUserId>", "NextOnStart": "N7", "PositionX": 170, "PositionY": 380 },
|
||||
"Approver": "<userName|email>", "NextOnStart": "N7", "PositionX": 170, "PositionY": 380 },
|
||||
|
||||
{ "Id": "N6", "Kind": "End", "Title": "Reddedildi", "PositionX": 340, "PositionY": 480 },
|
||||
{ "Id": "N7", "Kind": "End", "Title": "Onaylandı", "PositionX": 170, "PositionY": 480 }
|
||||
|
|
@ -2366,17 +2434,43 @@ Kurallar:
|
|||
|
||||
- **Id sözleşmesi:** `N` ile başlayan kısa id'ler seeder tarafından `{ListFormCode}-{Id}` hâline
|
||||
getirilir; hedef alanlar (`NextOn*`, `CompareOutcomes[].TargetId`) da aynı normalizasyondan
|
||||
geçer. Bu yüzden dosyada `N1`, `N2` yazman yeterlidir ve **tekil olmaları şarttır**.
|
||||
geçer (`N` ile başlayan her id, büyük/küçük harf duyarsız; diğer id'ler olduğu gibi kalır). Bu yüzden
|
||||
dosyada `N1`, `N2` yazman yeterlidir ve **tekil olmaları şarttır**. Runtime düğümleri
|
||||
`ListFormWorkflow` tablosundan okur; `WorkflowDto.Criteria` select cevabında tablodan doldurulur.
|
||||
- **Onaycı = kullanıcı adı / e-posta.** `Approver` `|` ile ayrılmış **kullanıcı adı ya da e-posta**
|
||||
listesidir; **rol ve Id desteklenmez** (onay yetkisi `CurrentUser.UserName/Email/Name` ile eşleşir).
|
||||
Rol bazlı onay gerekiyorsa `@Kolon` onaycısı + rolün kullanıcılarını kolona yazan prosedür kullanılır.
|
||||
Sabit `Approver` boş bırakılırsa ya da `ApprovalUserFieldName` tanımsızsa ekranın **Update yetkisi
|
||||
olan herkes** onaylayabilir — onay düğümünü onaycısız bırakma.
|
||||
- **Yetki ve görünürlük:** start/decision/reset/`reject-reasons` uçlarının hepsi ekranın **Update**
|
||||
yetkisini ister. Toolbar akış düğmeleri (Başlat dahil) yalnızca `ApprovalStatusFieldName` dolu, en az bir
|
||||
`Approval` düğümü var ve **`UpdateServiceAddress` boş değilse** görünür. Çoklu seçimde start/reset/
|
||||
decision her anahtar için ayrı çalışır.
|
||||
- **Yazma yolu:** her düğüm geçişi ekranın Update yoluyla yazar (`QueryManager`): `UpdateBefore/After`
|
||||
kancaları ve `UpdateFieldsDefaultValueJson` **her düğümde** çalışır, özel `UpdateCommand` varsa akış
|
||||
parametreleriyle o çalışır. Karar veren kullanıcının dört akış alanında (ve `RejectReason.TargetField`
|
||||
alanında) alan seviyesinde `U` yetkisi yoksa yazım **sessizce düşer**.
|
||||
- **Karar anı:** onaycı kolonuna karar verenin `UserName`'i, tarihe `Clock.Now`, açıklamaya
|
||||
`"{neden} - {not}"` yazılır. Durum boşken karar verilirse akış önce kendiliğinden başlatılır. Her işlem
|
||||
`Note` kaydı açar (`Type = "workflow"`, `EntityName = ListFormCode`, içerik HTML tablo); düğüm
|
||||
başlıkları dil anahtarı olabilir (sondaki rakam son ek olarak korunur).
|
||||
- **`End` düğümü:** onaycı kolonu boşsa admin e-postası, tarih boşsa `Clock.Now`, açıklama boşsa
|
||||
"Sistem tarafından otomatik olarak onaylandı." yazar. `NextOn*` boş kalan dal akışı sessizce bitirir
|
||||
(durumda son düğümün başlığı kalır); döngü hata verir.
|
||||
- `Compare` düğümünde çok dallı karar için `CompareOutcomes` kullanılır; iki dallı basit karar
|
||||
için `NextOnTrue` / `NextOnFalse` yeterlidir.
|
||||
Karşılaştırma **sayısaldır** (`EvaluateCondition`: `>`, `>=`, `<`, `<=`, `=`, `!=`); bit/metin kolon
|
||||
için `NextOnTrue` / `NextOnFalse` yeterlidir. Outcome'lar sırayla denenir, bir outcome'daki koşullar
|
||||
**AND** ile bağlanır, koşulsuz outcome "else" dalıdır; hiçbiri tutmazsa `NextOnTrue`/`NextOnFalse`
|
||||
kullanılır (kayıtta bu ikisi `outcomes[0]`/`[1]`'in hedefiyle ezilir). Koşulun kolonu satırda yoksa
|
||||
düğümün `CompareColumn`'u, o da yoksa satırdaki tek sayısal kolon kullanılır; değer `null` ise hata.
|
||||
Karşılaştırma **sayısaldır** (`EvaluateCondition`: `>`, `>=`, `<`, `<=`, `=`, `!=`; sunucu `==` ve `<>`'yi de kabul eder, bilinmeyen operatör `false`); bit/metin kolon
|
||||
okunamaz ve hata verir. Kayda göre adım atlamak için prosedür sayısal bir bayrak kolonu yazar ve
|
||||
kolon ekranda gizli alan olur (örnek: İzin Yönetimi'nde üst pozisyonu olmayan çalışanın müdür
|
||||
adımı, `RequiresManagerApproval`, `App.Hr.md` › İzin Yönetimi §5.6).
|
||||
- `Approval` düğümü `NextOnApprove` / `NextOnReject`, `Start` ve `Inform` düğümleri
|
||||
`NextOnStart` alanını kullanır. `End` düğümünün çıkışı yoktur.
|
||||
- **Red nedeni listesi:** `Approval` düğümü opsiyonel `RejectReason { TableName, ValueField, TextField,
|
||||
TargetField, Required }` taşır (entity'de `RejectReasonJson`). Boşsa red yalnızca açıklama ister; doluysa
|
||||
TargetField, Required }` taşır (entity'de `RejectReasonJson`; `Required` varsayılanı `true`, `TableName`/
|
||||
`ValueField`/`TextField` üçü dolu değilse tanım `null` saklanır; liste metin kolonuna göre sıralanır). Boşsa red yalnızca açıklama ister; doluysa
|
||||
karar diyaloğu tablonun Id/metin kolonlarından seçim listeler (`reject-reasons` ucu; tablo ekranın veri
|
||||
kaynağındadır, adlar katalogdan çözülür, `TenantId`/`IsDeleted`/`IsActive` kolonu varsa süzülür).
|
||||
`Required` açıkken neden seçilmeden ret verilemez. Seçilen nedenin metni açıklamanın başına
|
||||
|
|
@ -2388,12 +2482,18 @@ Kurallar:
|
|||
boşsa akış hata verir — boş onaycı herkese onay yetkisi verirdi. Kolonu kayıt sonrası prosedür doldurur
|
||||
(örnek: İzin Yönetimi'nde departman müdürü, `App.Hr.md` › İzin Yönetimi). Tasarımcıda onaycı listesi kullanıcılarla
|
||||
birlikte `Alan: {Kolon}` seçeneklerini sunar.
|
||||
- **`Inform` düğümü e-posta gönderir** (MailQueue üzerinden, `Approver` alanındaki kullanıcı/rol
|
||||
adreslerine, önceki adımların notlarıyla birlikte). Uygulama içi bildirim ya da SMS isteniyorsa
|
||||
- **`Inform` düğümü e-posta gönderir** — kuyruk değil, gönderici (`erpEmailSender`, Amazon SES) ile
|
||||
**senkron**; gönderim başarısızsa adım hata verip düşer. Alıcı `Approver`'daki değerlerdir: `@` içeren
|
||||
doğrudan e-posta, diğerleri kullanıcı adından çözülür; önceki adımların notları eklenir. Uygulama içi bildirim ya da SMS isteniyorsa
|
||||
ayrıca bir bildirim kuralı tanımlanır (§9.11).
|
||||
- `CompareValue` **sayısaldır** (`decimal`); metin karşılaştırması bu düğümle yapılmaz.
|
||||
- `Title` tekil olmalıdır; seeder tekrar eden başlıkları ayrıştırır ama okunabilirliği bozar.
|
||||
- Akış varsa ListForm `SelectionMode = single` olur ve not paneli otomatik açılır.
|
||||
- `Title` **işlevsel olarak** tekil olmalıdır: durum kolonu düğümün başlığını saklar, mevcut düğüm Id ya da
|
||||
başlıkla (büyük/küçük harf duyarsız) bulunur, toolbar onay düğmesi de başlıkla eşleşir. Kayıt çakışan
|
||||
başlığa numara ekler (`NormalizeUniqueTitleAsync`, wizard'da `EnsureUniqueWorkflowCriteriaTitles`).
|
||||
- Kayıt varsayılanları: `Kind` boşsa `Compare`, `CompareColumn` boşsa `Price`, `CompareOperator` boşsa `>`,
|
||||
`Title` boşsa `Kind`; konum ≤ 0 ise 32/150.
|
||||
- Akış varsa wizard ListForm'a `SelectionMode = single` yazar (runtime çoklu anahtarı da destekler) ve not
|
||||
paneli otomatik açılır. Wizard `ApprovalUserFieldName` ile `ApprovalStatusFieldName`'i zorunlu tutar.
|
||||
- Görsel tasarım `/admin/listform/edit/{kod}` → Workflow sekmesindedir.
|
||||
|
||||
### 4.8 `ListForm` entity — List component'in tek kaynağı
|
||||
|
|
@ -2409,9 +2509,9 @@ olmalıdır.
|
|||
| Kolon | Ne yapar |
|
||||
| --- | --- |
|
||||
| `ListFormCode` | Ekranın kodu; kullanıcı/rol/dil özelleştirmeleri buna bağlanır |
|
||||
| `CultureName` · `UserId` · `RoleId` | **Aynı ekranın varyantları.** Aynı `ListFormCode` ile ikinci bir kayıt açıp yalnızca bir rol ya da dil için farklı sütun/düzen verebilirsin |
|
||||
| `ListFormType` | `List` · `Form` — ekranın türü |
|
||||
| `IsSubForm` / `SubFormsListFormType` | Alt form olarak açıldığında davranış |
|
||||
| `CultureName` · `UserId` · `RoleId` | Dil varyantı (`CultureName`). `UserId`/`RoleId` ekran düzeyinde **okunmaz** — kullanıcı/rol farkı alan (`ListFormField`) ve kişiselleştirme düzeyindedir (reference §5.7) |
|
||||
| `ListFormType` | `List` · `Form` · `Chart` — ekranın türü |
|
||||
| `IsSubForm` / `SubFormsListFormType` | `IsSubForm` bilgi amaçlıdır; `SubFormsListFormType` bu ekranın alt form sekmelerinin yeri: `List` liste altında seçili satıra bağlı, `Form` yalnız detay sayfasında (reference §5.6) |
|
||||
|
||||
**Veri**
|
||||
|
||||
|
|
@ -2421,10 +2521,9 @@ olmalıdır.
|
|||
| `SelectCommandType` + `SelectCommand` | Kaynak türü ve kaynağın kendisi |
|
||||
| `TableName` | Tablo adı/alias — yazma komutlarının hedefi; `4` Query'de zorunlu alias (`"Q"`) |
|
||||
| `KeyFieldName` + `KeyFieldDbSourceType` | Anahtar; `4` Query'de ikisi de zorunlu |
|
||||
| `SelectFieldsDefaultValueJson` | Select'e geçirilen varsayılan parametreler |
|
||||
| `SelectFieldsDefaultValueJson` | Runtime **okumaz** (§4.3.5); okuma koşulu `DefaultFilter`'a yazılır |
|
||||
| `DefaultFilter` | Her sorgunun sonuna eklenen WHERE (soft delete filtresi buradadır) |
|
||||
| `IsTenant` · `IsBranch` · `IsOrganizationUnit` | Otomatik kırılım filtreleri |
|
||||
| `DataSourceJson` · `CommonJson` | Kaynak ve ortak ayarlar |
|
||||
| `IsTenant` · `IsBranch` · `IsOrganizationUnit` | Otomatik kırılım filtreleri (reference §4.2) |
|
||||
|
||||
**Yazma (CRUD)**
|
||||
|
||||
|
|
@ -2446,14 +2545,15 @@ kolonu vardır:
|
|||
| **Grid** | `ColumnOptionJson`, `RowJson`, `PagerOptionJson`, `SelectionJson`, `StateStoringJson` | — |
|
||||
| **Card** | `ColumnOptionJson` (kart alanları sütun tanımlarından türer) | — |
|
||||
| **Pivot** | `PivotOptionJson` + alan bazında `PivotSettingsJson` | — |
|
||||
| **Chart** | `SeriesJson`, `LegendJson`, `ArgumentAxisJson`, `ValueAxisJson`, `TooltipJson`, `PanesJson`, `AnnotationsJson`, `CrosshairJson`, `ScrollBarJson`, `ZoomAndPanJson`, `SizeJson`, `MarginJson`, `TitleJson`, `AnimationJson`, `Common*Json` | — (`SeriesJson` boşsa seri ekranda kurulur; grafik tarif edildiyse doldur, §9.8) |
|
||||
| **Chart** | `SeriesJson`, `CommonJson`, `AdaptiveLayoutJson`, `LegendJson`, `ArgumentAxisJson`, `ValueAxisJson`, `TooltipJson`, `PanesJson`, `AnnotationsJson`, `CrosshairJson`, `ScrollBarJson`, `ZoomAndPanJson`, `SizeJson`, `MarginJson`, `TitleJson`, `AnimationJson`, `Common*Json` | — (`SeriesJson` boşsa seri ekranda kurulur; grafik tarif edildiyse doldur, §9.8) |
|
||||
| **Tree** | `TreeOptionJson` | `KeyExpr` + `ParentIdExpr` |
|
||||
| **Gantt** | `GanttOptionJson` | `ParentIdExpr` + `TitleExpr` + `StartExpr` + `EndExpr` |
|
||||
| **Gantt** | `GanttOptionJson` | `KeyExpr` + `ParentIdExpr` + `TitleExpr` + `StartExpr` + `EndExpr` + `ProgressExpr` |
|
||||
| **Scheduler** | `SchedulerOptionJson` | `TextExpr` + `StartDateExpr` + `EndDateExpr` |
|
||||
| **Todo (Kanban)** | `TodoOptionJson` | `TitleExpr` + `StatusExpr` |
|
||||
|
||||
Sekiz layout **aynı `SelectCommand` üzerinden** beslenir; ayrı sorgu, ayrı ekran, ayrı menü
|
||||
gerekmez. Kullanıcı ekranın üstünden geçiş yapar, tercihi kullanıcı bazlı saklanır.
|
||||
gerekmez. Kullanıcı ekranın üstünden geçiş yapar; seçilen görünüm tarayıcının localStorage'ında
|
||||
saklanır (sunucuda değil). `Grid` her zaman açıktır.
|
||||
|
||||
Bu, tek bir metadata kaydından DevExtreme'in `DataGrid`, `CardView`, `PivotGrid`, `Chart`,
|
||||
`TreeList`, `Gantt` ve `Scheduler` bileşenlerinin tamamının sürülmesi demektir. **Todo layout
|
||||
|
|
@ -2469,12 +2569,12 @@ olarak da görelim" isteği yeni bir ekran değil, `Todo: true` + `TodoOptionDto
|
|||
| `ExtraFilterJson` | Ekrana özel ek filtre araç çubuğu |
|
||||
| `EditingOptionJson` | Düzenleme modu (row/cell/batch/form/popup), başlık, boyut, izinler |
|
||||
| `EditingFormJson` | Düzenleme formunun grup/sekme düzeni |
|
||||
| `CommandColumnJson` | Satır aksiyon sütunu |
|
||||
| `CommandColumnJson` | Özel toolbar ve satır butonları (§4.9); hazır butonlar reference §5.8 |
|
||||
| `PermissionJson` | Ekran yetkileri (create/read/update/delete/export/import/note) |
|
||||
| `SubFormsJson` · `WidgetsJson` · `WorkflowJson` | Alt formlar, KPI kartları, onay akışı |
|
||||
| `CustomJsSourcesJson` · `CustomStyleSourcesJson` | Sayfa yüklenince çalışan JS/CSS — **son çare** |
|
||||
| `Width` · `Height` · `FullHeight` · `AdaptiveLayoutJson` | Boyut ve uyarlanabilir yerleşim |
|
||||
| `ExportJson` | xlsx/csv/pdf dışa aktarma |
|
||||
| `Width` · `Height` · `FullHeight` | Boyut |
|
||||
| `ExportJson` | Dışa aktarma: `Enabled` + `PermissionJson.E`; Grid `pdf`/`xlsx`, Pivot `xlsx` (reference §5.8) |
|
||||
|
||||
**`ListFormField` — alan başına ayarlar**
|
||||
|
||||
|
|
@ -2547,18 +2647,24 @@ Kurallar:
|
|||
olmalıdır. İş akışı varsa wizard bunu zaten `single` yapar.
|
||||
- Toolbar butonu Grid, Card ve Tree'nin yanında **Todo panosunda** da çizilir; pano satır seçimi
|
||||
taşımadığı için orada yalnızca satırdan bağımsız `Url` ve `OnClick` butonları görünür
|
||||
(`DialogName` görünmez).
|
||||
(`DialogName` görünmez). **Form sayfasında** toolbar butonları ve Düzenle/Sil/Detay dışındaki satır
|
||||
butonları form araç çubuğuna taşınır (satır bağlamı enjekte edilir). Gantt, Scheduler, Pivot ve
|
||||
Chart'ta özel buton çizilmez. Buton anahtarı `Hint`'tir — aynı `Hint`'li iki buton yazma.
|
||||
- Satır bazlı aksiyon istiyorsan `ButtonPosition: 0` kullan; buton komut sütununda görünür.
|
||||
- **`IsVisible` ve `VisibleExpression` yalnızca satır butonlarında (`ButtonPosition: 0`)
|
||||
çalışır**; toolbar butonu her zaman görünür (görünürlüğü `AuthName` belirler).
|
||||
`VisibleExpression` bir ok fonksiyonudur ve `eval` edilir:
|
||||
`"(e) => e.row.data.Status === 'Taslak'"`.
|
||||
- URL token'ları: satır butonunda `@LISTFORMCODE` ve **grid sütunu olarak tanımlı** her alan için
|
||||
`@FieldName`; toolbar butonunda seçili ilk satırın tüm kolonları. Sütun listesinde olmayan bir
|
||||
alan adı satır butonunda değiştirilmez.
|
||||
`@FieldName`; toolbar butonunda seçili ilk satırın tüm kolonları (`@LISTFORMCODE` yok). Sütun
|
||||
listesinde olmayan bir alan adı satır butonunda değiştirilmez. Her token yalnızca **ilk geçtiği yerde**
|
||||
değiştirilir, değer URL-encode edilmez ve önek çakışır: `@Id`, `@IdentityNo` içinde de değişir —
|
||||
adı başka bir alan adının öneki olan alanı URL'de kullanma.
|
||||
`VisibleExpression` kart görünümünde `{row, card}`, form sayfasında `{row:{data,key,isEditing}}` alır.
|
||||
- **Diyalog modunda `@` parametreleri satır butonuna aittir**: değerleri satır verisinden okunur,
|
||||
toolbar'da satır bağlamı olmadığı için orada yalnızca sabit parametreler çalışır (yeni kayıt
|
||||
diyalogu için `{"id":""}` gibi). **`DialogParameters` boşsa diyalog hiç açılmaz** — bu yüzden
|
||||
diyalogu için `{"id":""}` gibi) — liste toolbar'ında `@` parametresi **çalışma anı hatası** verir;
|
||||
form sayfasında çalışır. **`DialogParameters` boşsa diyalog hiç açılmaz** — bu yüzden
|
||||
parametresiz diyaloglarda da en az bir sabit anahtar yazılır. Her iki konumda da diyalog
|
||||
kapanınca grid otomatik yenilenir.
|
||||
- `DialogName` **kayıtlı bir custom component adı değildir**; platformda tanımlı şu diyalogları
|
||||
|
|
@ -2664,8 +2770,8 @@ Builder'ı (§5) açar — çıktıları `EditorOptions`/`EditorScript` string'l
|
|||
|
||||
**Adım 7 — İş Akışı.** Zorunlu ikili: `ApprovalUserFieldName` + `ApprovalStatusFieldName`;
|
||||
opsiyonel `ApprovalDateFieldName`, `ApprovalDescriptionFieldName`, `ApprovalIsFilterUserName`
|
||||
(liste yalnız sıradaki onaycıya düşsün), `ApprovalIsResetWorkflow` (kayıt değişince akış başa
|
||||
dönsün), `ApprovalIsManualStart` (yeni kayıt taslak kalsın, akış başlat düğmesiyle başlasın). Onay düğümleri (`Criteria`) görsel akış tasarımcısında kurulur ve `ListFormWorkflow`
|
||||
(liste yalnız sıradaki onaycıya düşsün), `ApprovalIsResetWorkflow` (toolbar'a Workflow Reset
|
||||
düğmesi; otomatik sıfırlama yok), `ApprovalIsManualStart` (yeni kayıt taslak kalsın, akış başlat düğmesiyle başlasın). Onay düğümleri (`Criteria`) görsel akış tasarımcısında kurulur ve `ListFormWorkflow`
|
||||
kayıtlarına gider (§4.7).
|
||||
|
||||
**Adım 12 — Deploy.** Sol tarafta tüm adımların özeti, sağda üretim log'u. Log, deploy'un seed
|
||||
|
|
@ -2726,6 +2832,8 @@ karakter karakter karşılaştırır:
|
|||
| Tetikleyici kavramından önce yazılmış script (`trigger: change` ile yeniden üretim tutuyorsa) | Kurallar geçerli sayılır, yeni varsayılanlarla yükseltilir |
|
||||
| Metin farklı (elle düzenlenmiş) | Sihirbaz kuralları **ezmez**; sarı "kod ayrıştı" bandı çıkar. Kullanıcı bir kurala dokunana kadar kod olduğu gibi kalır; **Yeniden üret** düğmesi kodu kurallardan tazeler |
|
||||
| `// @builder` başlığı yok | Sihirbaz boş açılır; kural eklenirse **elle yazılmış kod tamamen değişir** |
|
||||
| Sihirbaz sekmesindeyken **Kaydet** | Kurala dokunulduysa ya da kod kurallarla aynıysa kurallardan üretilen metin yazılır; elle yazılmış (ayrışmış) kod kurala dokunulmadan kaydedilirse olduğu gibi kalır |
|
||||
| Kod sekmesinde bayat başlıklı script kaydı | Yalnızca ilk satır (`// @builder …`) silinir; `// @runOnOpen` kalır |
|
||||
|
||||
Bunun pratik karşılığı: **başlık ile gövdeyi ayrı ayrı düzenleme.** Seeder ile basılan script'in
|
||||
dialogda açılabilir kalması, C# tarafının (§5.9) TS tarifleriyle birebir aynı metni üretmesine
|
||||
|
|
@ -2813,9 +2921,18 @@ Script'in **herhangi bir** kuralı açılışta çalışıyorsa metnin başına
|
|||
her satır kendi tetikleyicisine göre sarmalanır: `change` → `if (!isReady) …`,
|
||||
`open` → `if (isReady) …`. Hiçbir kural açılışta çalışmıyorsa guard üretilmez, kod kısa kalır.
|
||||
|
||||
> **Açılışta çalışmanın ikinci tetiği:** script yalnızca `// @runOnOpen` ile değil, metninde
|
||||
> `readOnly(`, `isReady`, `setEditorReadOnly` ya da `runtimeSetEditorReadOnly` geçtiğinde de form
|
||||
> açılışında çalışır (`shouldRunEditorScriptOnContentReady`, `list/shared/editingForm.ts`). Tetikleyicisi
|
||||
> `change` olan bir `readOnly` kuralı guard üretmez ama script yine açılışta koşar; aynı script'teki
|
||||
> guard'sız `ask`/`notify`/`api` satırları da **her açılışta** çalışır. `readOnly` kuralını uyarı/servis
|
||||
> kurallarıyla aynı alana koyuyorsan tetikleyicisini `both` yap ki diğer satırlar `if (!isReady)` ile
|
||||
> sarmalansın.
|
||||
|
||||
Açılışta çalışma güvenliği runtime tarafında korunur: değişmeyen değer yazılmaz
|
||||
(`Object.is` kontrolü), yazmalar bir tick sonraya alınır ve aynı turda tekrar girilmez —
|
||||
yoksa `contentReady` kendini besleyip sonsuz döngü olurdu.
|
||||
(`Object.is` kontrolü), yazmalar ertelenir (Grid/Tree `onContentReady`'de `setTimeout 0`, runtime
|
||||
flush'ı `queueMicrotask`) ve aynı turda tekrar girilmez — yoksa `contentReady` kendini besleyip
|
||||
sonsuz döngü olurdu.
|
||||
|
||||
### 5.6 Runtime API — script'in içinde ne varsa
|
||||
|
||||
|
|
@ -2828,22 +2945,22 @@ Script `AsyncFunction` ile derlenir, aşağıdaki adlar parametre olarak enjekte
|
|||
| `data` | Script'in üzerinde çalıştığı canlı form verisi (kopya) |
|
||||
| `isReady` | `true` ise script form açılışında çalışıyor |
|
||||
| `get('Alan')` | Form verisinden okur. **Nokta yolu** (`Musteri.Unvan`) ve **büyük/küçük harf duyarsız** eşleşme destekler (SQL kolon adları tutarsız gelebiliyor) |
|
||||
| `num()` · `str()` · `bool()` | **Alan adı** alır, değeri değil: `str('ProductType')`. `str(get('X'))` ya da `str(value)` değeri alan adı sanıp boş döner — koşul hiç tutmaz. Değişen alanın değeri için `str(field)` ya da doğrudan `value` kullanılır. `bool` için `true`/`'true'`/`1`/`'1'` doğrudur |
|
||||
| `num()` · `str()` · `bool()` | **Alan adı** alır, değeri değil: `str('ProductType')`. `str(get('X'))` ya da `str(value)` değeri alan adı sanıp boş döner — koşul hiç tutmaz. Değişen alanın değeri için `str(field)` ya da doğrudan `value` kullanılır. `bool` için `true`/`'true'`/`1`/`'1'` doğrudur; `num` sayıya çevrilemeyen değerde `0` döner |
|
||||
| `dateOf('Alan')` | `Date` ya da `null` |
|
||||
| `pick(nesne, 'a.b')` | Herhangi bir nesneden yol okuma |
|
||||
| `set('Alan', deger)` · `set({A:1, B:2})` | Yazar. Değişmeyen değer yazılmaz; yazmalar biriktirilip **tek flush** ile forma ve düzenlenen grid hücresine uygulanır |
|
||||
| `clear('A','B')` | Verilen alanları `null` yapar |
|
||||
| `copy('kolon','Alan')` | Lookup/GridBox'ta **seçili kayıttan** taşır; hedef verilmezse yolun son parçası hedef olur. Seçili kayıt, olay formdan gelse de (popup form, form sayfası) değişen alanın editöründen okunur; lookup sorgusu taşınacak kolonları döndürmelidir (ör. `SELECT Id AS [Key], …, DepartmentId, JobPositionId`) |
|
||||
| `copy('kolon','Alan')` | Lookup/GridBox'ta **seçili kayıttan** taşır; hedef verilmezse yolun son parçası hedef olur. Seçili kayıt, olay formdan gelse de (popup form, form sayfası) değişen alanın editöründen okunur; lookup sorgusu taşınacak kolonları döndürmelidir (ör. `SELECT Id AS [Key], …, DepartmentId, JobPositionId`). Seçili kayıt yoksa sessizce hiçbir şey yapmaz |
|
||||
| `selected('Yol')` · `snum()` · `sstr()` | Seçili kaydın tamamı / sayı / metin hâli |
|
||||
| `readOnly('Alan', kosul)` | Formdaki **herhangi bir** editörü kilitler/açar (yalnızca script'in bağlı olduğu alanı değil). Grid popup'ında açılış çalışması (`isReady`) form her yeniden çizildiğinde (her `cellValue` yazımı) tekrarlanır; veri grid'in düzenlenen satırından güncel okunur (`getEditingRow`), `str('Alan')` yeterlidir |
|
||||
| `round(x, 2)` · `sum('A','B')` | Matematik |
|
||||
| `days('Bas','Bit')` · `hours('Bas','Bit')` | Gün farkı (bitiş dahil) · saat farkı (negatifse +24) |
|
||||
| `tpl('{Alan} - {value}')` | Şablon: `{Alan}`, `{value}`, `{selected.Yol}` |
|
||||
| `days('Bas','Bit')` · `hours('Bas','Bit')` | Gün farkı (bitiş dahil; negatif sonuç `0`'a kırpılır) · saat farkı (negatifse +24, `0,1`'e yuvarlanır). Tarihlerden biri boşsa ikisi de `null` döner |
|
||||
| `tpl('{Alan} - {value}')` | Şablon: `{Alan}` (nokta yolu destekler), `{value}`, `{selected.Yol}` — çözüm sırası `{value}` → `{selected.X}` → `{Alan}` |
|
||||
| `notify('mesaj')` | `window.alert` (şablon çözülür) |
|
||||
| `ask('mesaj')` | `window.confirm`; hayır denirse `revert()` çalışır ve `false` döner |
|
||||
| `revert()` | Alanı değişiklik öncesi değerine döndürür (editöre de yazar) |
|
||||
| `openUrl('/adres', '_blank')` | Yeni sekme/pencere |
|
||||
| `await api(url, 'data.name', options?)` | `/api/` ile başlayan uygulama adresi platform istemcisinden gider (oturum + kiracı başlığı; `options.method`/`options.body` taşınır). Dış adres ham `fetch`'tir, başlık eklemez. |
|
||||
| `openUrl('/adres', '_blank')` | Yeni sekme/pencere; hedef verilmezse `_blank` |
|
||||
| `await api(url, 'data.name', options?)` | `/api/` ile başlayan uygulama adresi platform istemcisinden gider (oturum + kiracı başlığı; `options.method`/`options.body` taşınır). Dış adres ham `fetch`'tir, başlık eklemez. `/api/` adresinde metin `options.body` önce `JSON.parse` edilir. |
|
||||
| `await geoTo('Lat', 'Lng', 'Acc'?)` | Cihaz konumunu alanlara yazar. İzin yoksa/okunamazsa alanlara **dokunmaz** ve uyarı gösterir, `false` döner |
|
||||
| `$` | Tüm yardımcıların tek nesne hâli |
|
||||
|
||||
|
|
@ -2876,7 +2993,8 @@ durdurur. Script Builder kaydetmeden önce metni derler ve hatada kaydetmez (`Ap
|
|||
**Script Builder ile MCP aynı kodu üretir.** Kod `// @builder` başlığındaki kurallardan üretilir; MCP/wizard
|
||||
deploy'u gövdeyi atıp kuralları `EditorScript.Rebuild` ile yeniden üretir (C# çıktısı `scriptRecipes.ts` ile
|
||||
birebir). Onay kutusu/anahtar alanına değer yazan `setValue` kuralında dialog serbest metin yerine Evet/Hayır
|
||||
sectirir (`getParamChoices`); deploy aynı alana gelen `0`/`1`/`evet`/`hayır` değerini `true`/`false`'a çevirir.
|
||||
sectirir (`getParamChoices`); deploy aynı alana gelen `true`/`1`/`yes`/`evet`/`on` değerini `true`'ya,
|
||||
`false`/`0`/`no`/`hayir`/`hayır`/`off` değerini `false`'a çevirir (`WithBooleanValue`).
|
||||
Kod editöründe kurallarla eşleşmeyecek şekilde elle değiştirilen script'te dialog uyarır
|
||||
(`App.ScriptBuilder.StaleHeader`) ve kaydederken bayat başlığı siler; başlık kalsaydı deploy gövdeyi başlıktan
|
||||
yeniden üretip elle yapılan düzeltmeyi geri alırdı.
|
||||
|
|
@ -2894,7 +3012,8 @@ için `invert` boş bırakılır.
|
|||
- Script bir alana bağlıdır: `X` alanının script'i yalnızca `X` değiştiğinde (ve açılışta)
|
||||
çalışır. Üç alandan beslenen bir toplam için ya her birine kural yaz ya da toplamı üreten
|
||||
kuralı üç alanın script'ine de koy.
|
||||
- Hata yönetimi: script hatası konsola yazılır, kullanıcıya gösterilmez ve form akışını kesmez.
|
||||
- Hata yönetimi: script hatası kullanıcıya `App.EditorScript.Error` bildirimiyle gösterilir (aynı hata 5 sn
|
||||
içinde tekrar gösterilmez); derleme hatası script'in tamamını durdurur, çalışma hatası form akışını kesmez.
|
||||
|
||||
### 5.8 Kod modunda çalışmak
|
||||
|
||||
|
|
@ -2920,7 +3039,7 @@ if (isReady) {
|
|||
| --- | --- |
|
||||
| multiply / subtract | `EditorScript.Multiply(left, right, target, digits)` · `Subtract(...)` |
|
||||
| percent | `EditorScript.Percent(amount, rate, target, digits, EditorScriptPercentMode.Add\|Subtract\|Only)` |
|
||||
| sum | `EditorScript.Sum(target, "A", "B")` |
|
||||
| sum | `EditorScript.Sum(target, "A", "B")` · `Sum(target, IEnumerable<string> fields, digits)` |
|
||||
| formula | `EditorScript.Formula(target, "num('Gross') * 0.18")` |
|
||||
| today / days / hours | `Today(target, offsetDays)` · `Days(start, end, target)` · `Hours(start, end, target)` |
|
||||
| copy / setValue / clear | `Copy(sourcePath, target)` · `SetValue(target, text)` · `Clear("Il", "Ilce")` |
|
||||
|
|
@ -2928,6 +3047,11 @@ if (isReady) {
|
|||
| notify / ask / openUrl | `Notify(message)` · `Ask(message)` · `OpenUrl(url, target)` |
|
||||
| apiToField / location / custom | `ApiToField(target, url, responsePath)` · `Location(latField, lngField, accuracyField)` · `Custom(code)` |
|
||||
|
||||
Toplu üretim: `EditorScript.Build(params rules)`; tek kural `EditorScriptRule.ToScript()` ya da örtük
|
||||
`string` dönüşümü; var olan script'in gövdesini başlıktaki kurallardan yeniden üretmek
|
||||
`EditorScript.Rebuild(script, isBooleanField)` (wizard/MCP deploy bunu çağırır). `percent` modunda
|
||||
`Only` = `null` (yalnızca tutar), `EditorScriptTrigger.Default` = grup varsayılanı.
|
||||
|
||||
Akıcı ekler: `.When(...)` (hepsi sağlanmalı), `.WhenAny(...)` (biri yeterli),
|
||||
`.OnChange()` / `.OnOpen()` / `.OnOpenAndChange()` / `.WithTrigger(EditorScriptTrigger.X)`,
|
||||
`.WithId("multiply_1")` (verilmezse tarif adı + sıra numarasından üretilir).
|
||||
|
|
@ -2956,6 +3080,8 @@ EditorScript = EditorScript.Days("StartDate", "EndDate", "DayCount");
|
|||
> **Eşleme kuralı:** `scriptRecipes.ts` ile bu sınıflar aynı çıktıyı üretmek zorundadır. Birinde
|
||||
> bir tarif değişirse aynı görevde diğeri de değişir; aksi hâlde seeder ile basılan script
|
||||
> dialogda "elle düzenlenmiş" sayılır ve kural editörü kapanır.
|
||||
> İki tarafta aynı kurallar: `custom` yalnızca sondaki tek `;`'ü siler, `today` ofseti tam güne kırpılır,
|
||||
> ek `always` koşulları başlıkta korunur.
|
||||
|
||||
### 5.10 Senaryo → kural dizisi
|
||||
|
||||
|
|
@ -3016,22 +3142,24 @@ Dizi elemanları yaprak sayılmaz; `toolbar.items` tek bir `json` alanıdır.
|
|||
| Grup | Anahtarlar | Hangi editörlerde |
|
||||
| --- | --- | --- |
|
||||
| Genel | `readOnly`, `disabled`, `visible`, `hint`, `tabIndex`, `valueChangeEvent`, `validationMessageMode`, `validationMessagePosition`, `elementAttr.class`, `inputAttr.style`, `inputAttr.aria-label` | hepsi |
|
||||
| Görünüm | `width`, `height`, `placeholder`, `label`, `labelMode`, `stylingMode`, `showClearButton` | hepsi (giriş kutusu olmayanlarda `placeholder`/`showClearButton` anlamsız) |
|
||||
| Metin | `mode`, `maxLength`, `mask`, `maskChar`, `maskRules.X`, `maskInvalidMessage`, `showMaskMode`, `useMaskedValue`, `spellcheck`, `autoResizeEnabled`, `minHeight`, `maxHeight` | `dxTextBox`, `dxTextArea`, `dxAutocomplete` |
|
||||
| Sayı | `min`, `max`, `step`, `showSpinButtons`, `useLargeSpinButtons`, `format.type`, `format.precision`, `format.currency`, `invalidValueMessage`, `useMaskBehavior` | `dxNumberBox` |
|
||||
| Görünüm | `width`, `height`, `placeholder`, `label`, `labelMode`, `stylingMode`, `showClearButton`\* | hepsi (giriş kutusu olmayanlarda `placeholder`/`showClearButton` anlamsız) |
|
||||
| Metin | `mode`, `maxLength`, `mask`, `maskChar`, `maskRules.X`, `maskInvalidMessage`, `showMaskMode`, `useMaskedValue`, `spellcheck` · yalnız `dxTextArea`: `autoResizeEnabled`, `minHeight`, `maxHeight` | `dxTextBox`, `dxTextArea`, `dxAutocomplete` |
|
||||
| Sayı | `min`, `max`, `step`, `showSpinButtons`, `useLargeSpinButtons`, `format.type`, `format.precision`, `format.currency`, `invalidValueMessage`, `useMaskBehavior` | `dxNumberBox` (`useMaskBehavior` `dxDateBox`'ta da görünür) |
|
||||
| Tarih | `type`, `pickerType`, `displayFormat`, `dateSerializationFormat`, `interval`, `min`, `max`, `openOnFieldClick`, `applyValueMode`, `invalidDateMessage`, `calendarOptions.firstDayOfWeek`, `calendarOptions.zoomLevel` | `dxDateBox`, `dxCalendar`, `dxDateRangeBox` |
|
||||
| Açılır liste | `searchEnabled`\*, `searchMode`, `searchExpr`, `searchTimeout`, `minSearchLength`, `showDataBeforeSearch`, `acceptCustomValue`\*, `noDataText`, `deferRendering`, `wrapItemText`, `dropDownOptions.width/height/hideOnOutsideClick` | `dxSelectBox`, `dxLookup`, `dxTagBox`, `dxDropDownBox`, `dxGridBox`, `dxAutocomplete` |
|
||||
| Açılır liste | `searchEnabled` (\* yalnız TagBox DTO'sunda), `searchMode`, `searchExpr`, `searchTimeout`, `minSearchLength`, `showDataBeforeSearch`, `acceptCustomValue`\*, `noDataText`, `deferRendering`, `wrapItemText`, `dropDownOptions.width/height/hideOnOutsideClick` | `dxSelectBox`, `dxLookup`, `dxTagBox`, `dxDropDownBox`, `dxGridBox`, `dxAutocomplete` |
|
||||
| TagBox | `showSelectionControls`\*, `maxDisplayedTags`\*, `showMultiTagOnly`\*, `applyValueMode`\*, `multiline`, `hideSelectedItems` | `dxTagBox` |
|
||||
| GridBox | `columns`\*, `selectionMode`\*, `filterRowVisible`\* | `dxGridBox` |
|
||||
| Görsel | `uploadUrl`\*, `fileFieldName`, `accept`\*, `capture`\*, `multiple`\*, `maxFileSize`\* | `dxImageUpload`, `dxImageViewer` |
|
||||
| Görsel | `width`\*, `height`\*, `uploadUrl`\*, `fileFieldName`, `accept`\*, `capture`\*, `multiple`\*, `maxFileSize`\* | `dxImageUpload`, `dxImageViewer` |
|
||||
| Seçim | `text` (`dxCheckBox`), `switchedOnText`/`switchedOffText` (`dxSwitch`), `layout` (`dxRadioGroup`), `editAlphaChannel`/`keyStep` (`dxColorBox`), `count`/`allowClear` (`dxRating`) | ilgili editör |
|
||||
| Kaydırıcı | `min`, `max`, `step`, `tooltip.enabled`, `tooltip.showMode`, `showRange` | `dxSlider`, `dxRangeSlider` |
|
||||
| HTML | `valueType`, `toolbar.multiline`, `toolbar.items`, `mediaResizing.enabled`, `imageUpload.tabs`, `imageUpload.fileUploadMode`, `imageUpload.uploadUrl`, `tableResizing.enabled`, `tableContextMenu.enabled` | `dxHtmlEditor` |
|
||||
| Liste sütunu | `format` (metin hâli), `encodeHtml`, `buttons` | hepsi — bu üçü **grid sütununu** da etkiler |
|
||||
| Liste sütunu | `format` (metin hâli; telefon token'ları `phoneGlobal`/`phoneTR`/`phoneIntl`/`phoneCountry` — §6.4.1), `encodeHtml`, `buttons` | hepsi — bu üçü **grid sütununu** da etkiler |
|
||||
| Sözlük dışı | `phoneCountryField` (`phoneCountry` ile ülke alanının adı) — sözlükte yok, preset ya da "Sözlük dışı ayarlar" bölümünden yazılır | `dxTextBox` |
|
||||
|
||||
`\*` işaretli anahtarlar backend'de tipli DTO'ya (`GridBoxOptionsDto`, `TagBoxOptionsDto`,
|
||||
`ImageUploadOptionsDto`) çözülür; yanlış tipte yazılan değer hata vermez, **sessizce yok sayılır**.
|
||||
`columns` dizi, `maxDisplayedTags` sayı, `multiple` boolean olmalıdır.
|
||||
`columns` dizi, `maxDisplayedTags` sayı, `multiple` boolean olmalıdır. `\*` işaretli
|
||||
`showClearButton` GridBox ve TagBox DTO'sundadır, Görsel'in `width`/`height`'ı `ImageUploadOptionsDto`'dadır.
|
||||
|
||||
### 6.4 Hazır kalıplar (preset)
|
||||
|
||||
|
|
@ -3043,16 +3171,16 @@ Preset mevcut JSON ile **birleşir**, diğer ayarları silmez; aynı anahtar var
|
|||
| Sağa hizalı | `{"inputAttr":{"style":"text-align: right"}}` |
|
||||
| 2 ondalık · Artırmalı sayı · Para | `format.fixedPoint(2)` · + `useMaskBehavior` + `showSpinButtons` · `format.currency TRY` |
|
||||
| Tarih · Tarih-saat · Saat | `type`+`displayFormat`+`dateSerializationFormat` üçlüsü (saatte ayrıca `pickerType:list`, `interval`, `width:100%`) |
|
||||
| Telefon maskesi | `mask`, `maskRules.X`, `maskInvalidMessage`, `placeholder` |
|
||||
| Telefon (Türkiye) · (uluslararası) · (ülkeye göre) | `{"format":"phoneTR"}` · `{"format":"phoneIntl"}` · `{"format":"phoneCountry","phoneCountryField":"Country"}` — ayrıntı §6.4.1 |
|
||||
| Otomatik büyüyen metin | `autoResizeEnabled`, `minHeight`, `maxHeight` |
|
||||
| Telefon maskesi | `mask`, `maskRules.X`, `maskInvalidMessage`, `placeholder`, `useMaskedValue:false` — token değil sabit maskedir; `phoneGlobal` token'ının preset'i yoktur, `format` alanına elle yazılır |
|
||||
| Telefon (Türkiye) · (uluslararası) · (ülkeye göre) | `{"format":"phoneTR"}` · `{"format":"phoneIntl"}` · `{"format":"phoneCountry","phoneCountryField":"Country"}` — üçü de `showClearButton:true` ekler; ayrıntı §6.4.1 |
|
||||
| Otomatik büyüyen metin | `autoResizeEnabled`, `minHeight:80`, `maxHeight:320` |
|
||||
| Aranabilir liste | `searchEnabled`, `searchMode:contains`, `searchTimeout`, `showClearButton` |
|
||||
| TagBox anında seçim | `showSelectionControls`, `applyValueMode:instantly`, `searchEnabled` |
|
||||
| GridBox tek/çok seçim | `columns`, `selectionMode`, `filterRowVisible`, `height`, `width` |
|
||||
| TagBox anında seçim | `showSelectionControls`, `applyValueMode:instantly`, `searchEnabled`, `showClearButton` |
|
||||
| GridBox tek/çok seçim | `columns`, `selectionMode`, `filterRowVisible`, `width`×`height` (tek 320×520 + `showClearButton`, çok 360×560) |
|
||||
| Çoklu görsel | `width`, `height`, `multiple`, `accept:image/*` |
|
||||
| HTML tam araç çubuğu | `htmlEditorOptions.ts` varsayılanı: `toolbar.items` (tam liste), `toolbar.multiline`, `mediaResizing`, `imageUpload` (`tabs: file/url`, base64), `tableResizing`, `tableContextMenu` — boş `editorOptions` da aynı varsayılanı alır |
|
||||
| Yükseklik 100 / 200 | `{"height":100}` · `{"height":200}` |
|
||||
| Barkod okutma butonu | `buttons[]` — kamera ikonlu buton; `onClick` = `"@SCAN_BARCODE"` token'ı. Yalnız `dxTextBox`. Token'ı `resolveEditorButtons` (`editingForm.ts`) kamera diyaloğuna bağlar, okunan kod alana yazılır; liste popup'ı ve form sayfası aynı. HTTPS şart. Fonksiyon metni yazılan `onClick` olayla birlikte `formData`, `fieldName`, `mode` alır (popup'ta ek olarak `rowKey`, `rowIndex`). |
|
||||
| Barkod okutma butonu | `buttons[]` — `{name:"scanBarcode", location:"after", icon:"photo"}`; `onClick` = `"@SCAN_BARCODE"` token'ı. Yalnız `dxTextBox`. Token'ı `resolveEditorButtons` (`editingForm.ts`) kamera diyaloğuna bağlar, okunan kod alana yazılır; liste popup'ı ve form sayfası aynı. HTTPS şart. Fonksiyon metni yazılan `onClick` olayla birlikte `formData`, `fieldName`, `mode` alır (popup'ta ek olarak `rowKey`, `rowIndex`). |
|
||||
| Kamerayla foto çek | `{"accept":"image/*","capture":"environment"}` — yalnız `dxImageUpload`. Mobilde dosya seçici yerine **yalnızca** kamera açılır (`user` = ön kamera); masaüstünde yok sayılır. Ayarlanmazsa dokunmatik cihazda dosya seçicinin yanına ayrı bir kamera butonu gelir, yani ikisi birden kullanılabilir — bu kalıp kamerayı **zorunlu** kılmak içindir. |
|
||||
|
||||
#### 6.4.1 Telefon biçimleri (`format` token'ı)
|
||||
|
|
@ -3085,6 +3213,8 @@ varsayılanı ezer.
|
|||
- Ülke listesi `GET /api/app/public/country`'den bir kez yüklenir ve önbellekte kalır.
|
||||
- Dinamik raporlar (Grid/Tree/Form) aynı biçimi sunucuda `DynamicReportPhoneFormatter` ile basar; `phoneCountry`
|
||||
kolonu satırın ülke kolonunu biçim ifadesine beşinci operand olarak verir. Kural `phoneFormat.ts` ile birebir aynıdır.
|
||||
- Listede `phoneGlobal`/`phoneTR` değeri 10 haneden kısaysa **ham** gösterilir, uzunsa son 10 hane alınır.
|
||||
Bilinmeyen `format` değeri `phoneGlobal` gibi davranır. `phoneIntl` örneği `+90 532 123 45 67`'dir.
|
||||
|
||||
### 6.5 Seeder tarafı (C#)
|
||||
|
||||
|
|
@ -3094,13 +3224,13 @@ varsayılanı ezer.
|
|||
| Temizle düğmesi | `EditorOptions.ShowClearButton()` | `{"showClearButton":true}` |
|
||||
| Çok satırlı | `EditorOptions.Multiline(80)` | `{"height":80}` |
|
||||
| Sabit ondalık | `EditorOptions.Number(2)` | format + maske davranışı + spin |
|
||||
| Yüzde | `EditorOptions.Percent()` | |
|
||||
| Tarih / tarih-saat / saat | `EditorOptions.Date()` · `DateTime()` · `Time(15)` | |
|
||||
| Telefon | `EditorOptions.Phone()` | global format + maske + örnek |
|
||||
| Yüzde | `EditorOptions.Percent()` | `{"format":"#0.##'%'","useMaskBehavior":true,"showSpinButtons":true}` |
|
||||
| Tarih / tarih-saat / saat | `EditorOptions.Date()` · `DateTime()` · `Time(15)` | Tarih/tarih-saat: `format` + `displayFormat` (UI preset'inden farklı olarak `type` ve `dateSerializationFormat` yazmaz). Saat: `type:time`, `pickerType:list`, `displayFormat:HH:mm`, `dateSerializationFormat`, `interval`, `width:100%` — UI preset'iyle aynı |
|
||||
| Telefon | `EditorOptions.Phone()` | `format:"phoneGlobal"` + `mask` + `maskInvalidMessage` + `useMaskedValue:false` + `maskRules` + `placeholder` |
|
||||
| Telefon (ülkeye göre) | `EditorOptions.PhoneByCountry("Country")` | `{"format":"phoneCountry","phoneCountryField":"Country","showClearButton":true}` |
|
||||
| Kaydırıcı | `EditorOptions.Slider()` | `{"tooltip":{"enabled":true}}` |
|
||||
| Görsel yükleme | `EditorOptions.ImageUpload(multiple: true, 80, 80)` | |
|
||||
| Zengin metin | `EditorOptions.Html(240)` | `htmlEditorOptions.ts` varsayılanıyla aynı bloklar (tam araç çubuğu, `imageUpload`, `mediaResizing`, `tableResizing`, `tableContextMenu`; biri değişirse diğeri de değişir) + `encodeHtml` + `elementAttr` `min-height:240px` (sabit yükseklik değil; içerikle büyür) |
|
||||
| Görsel yükleme | `EditorOptions.ImageUpload(multiple: true, 80, 80)` | `width`/`height`/`multiple` (UI preset'indeki `accept:"image/*"` yok — gerekiyorsa `.Text("accept","image/*")`) |
|
||||
| Zengin metin | `EditorOptions.Html(240)` | `htmlEditorOptions.ts` varsayılanıyla aynı bloklar (tam araç çubuğu, `imageUpload`, `mediaResizing`, `tableResizing`, `tableContextMenu`; biri değişirse diğeri de değişir) + `encodeHtml` + `elementAttr` `min-height:240px` (sabit yükseklik değil; içerikle büyür; varsayılan `minHeight` 200). `elementAttr`'ı tamamen yazar — aynı JSON'daki `elementAttr.class` kaybolur |
|
||||
|
||||
Akıcı ekler: `.Placeholder()`, `.MaxLength()`, `.Height(int\|string)`, `.Width(int\|string)`,
|
||||
`.Format()`, `.FixedPointFormat(p)`, `.DisplayFormat()`, `.DateSerializationFormat()`,
|
||||
|
|
@ -3120,6 +3250,9 @@ Kurallar:
|
|||
- Aynı anahtar iki kez verilirse sonuncusu geçerlidir; anahtar sırası korunur.
|
||||
- `.Raw` değeri **geçerli JSON** olmalıdır; doğrulanmaz.
|
||||
- Hiç seçenek yoksa `Build()` boş metin döner — alan `null` kalır, `{}` yazılmaz.
|
||||
- C# karşılığı olmayan UI preset'leri (para, sağa hizalı, `phoneTR`/`phoneIntl`, otomatik büyüyen metin,
|
||||
aranabilir liste, TagBox anında seçim, GridBox tek/çok, kamerayla foto, barkod butonu) genel
|
||||
yazıcılarla kurulur: `.Text("format","phoneTR")`, `.Raw("buttons", "[…]")`.
|
||||
|
||||
### 6.6 `EditorScript` mi `EditorOptions` mı?
|
||||
|
||||
|
|
@ -3337,14 +3470,17 @@ olarak taşır (`?Name.contains=abc`). Bu, CrudEndpoint `GetList`'in okuduğu s
|
|||
**Önce yeniden kullan:** istenen şey zaten bir ListForm ekranının verdiği liste/ağaç/grafikse,
|
||||
onu primitiflerden yeniden kurma — ilgili `platform` düğümünü `listFormCode` ile bırak.
|
||||
|
||||
> **Önemli — eksik olan eklenir, yeni bileşen yazılmaz.** İstenen komponent Developer Kit
|
||||
> araçlarıyla (toolbox + konfigürasyon) büyük ölçüde — diyelim %70 — kuruluyorsa geri kalanı
|
||||
> "yapılamaz" ya da sessizce atlanacak bir şey değildir; ama çözüm **yeni bir bileşen / aile /
|
||||
> Developer Kit ekranı üretmek de değildir**. Kullanılan **var olan bileşene küçük eklemeler**
|
||||
> yapılır ve komponent tamamlanır. Eklenebilecekler: eksik bir **olay** (`onBlur`, `onKeyDown`,
|
||||
> `onDoubleClick`…), eksik bir **prop** (`maxLength`, `prefix`, `readOnly`, `variant` değeri,
|
||||
> `size`…) ya da bileşenin var olan davranışını bozmadan eklenen **küçük bir yetenek**
|
||||
> (ikon slotu, ek görünüm seçeneği, `ref` API'sine yeni metot). Geliştirme zinciri:
|
||||
> **Önemli — eksik olan Core'dur, komutla eklenir; yeni bileşen yazılmaz.** İstenen komponent
|
||||
> Developer Kit araçlarıyla (toolbox + konfigürasyon) büyük ölçüde kuruluyor ama bir bileşende
|
||||
> olay, prop ya da küçük bir yetenek eksikse: komponent hazır araçlarla kurulabildiği kadar
|
||||
> **üretilir**, eksik parça "yapılamaz" denip sessizce atlanmaz, son mesajda "Core gerektiren
|
||||
> kısım" notuyla bildirilir (§0.8). Kullanıcı **"core sisteme ekle"** derse çözüm yine yeni bir
|
||||
> bileşen / aile / Developer Kit ekranı değildir; **var olan bileşene küçük ekleme** yapılır:
|
||||
> eksik bir **olay** (`onBlur`, `onKeyDown`, `onDoubleClick`…), eksik bir **prop** (`maxLength`,
|
||||
> `prefix`, `readOnly`, `variant` değeri, `size`…) ya da var olan davranışı bozmadan eklenen
|
||||
> **küçük bir yetenek** (ikon slotu, ek görünüm seçeneği, `ref` API'sine yeni metot). Önce ilk
|
||||
> satıra bak: olay/prop bileşende zaten varsa iş yalnızca panelde göstermektir — o da `ui/`
|
||||
> değişikliğidir ve komut ister. Komutla çalışan geliştirme zinciri:
|
||||
>
|
||||
> | Durum | Yapılacak (hepsi mevcut dosyalarda, yeni bileşen dosyası yok) |
|
||||
> | --- | --- |
|
||||
|
|
@ -3358,8 +3494,8 @@ onu primitiflerden yeniden kurma — ilgili `platform` düğümünü `listFormCo
|
|||
> `EXCLUDED_COMPONENTS`'ten bileşen çıkarma, Developer Kit menüsüne yeni ekran/komponent,
|
||||
> bileşenin mevcut davranışını/varsayılanını değiştiren ekleme (geriye dönük uyumluluk şart —
|
||||
> var olan custom component'ler aynı çıktıyı vermeye devam etmeli). Ekleme "küçük" değilse
|
||||
> (bileşeni yeniden yazmak, ikinci bir bileşen gibi davranmasını sağlamak) bu çerçeve dışıdır
|
||||
> ve §0.8'e göre sorulur.
|
||||
> (bileşeni yeniden yazmak, ikinci bir bileşen gibi davranmasını sağlamak) komut o ekleme için
|
||||
> açıkça verilmiş olmalıdır (§0.8).
|
||||
>
|
||||
> İhtiyaç görsel davranış değil de veri/aksiyonsa Custom Endpoint (§9.2), iş mantığıysa
|
||||
> Dynamic Service (§9.3, §10.6) her zaman açıktır.
|
||||
|
|
@ -4617,6 +4753,12 @@ Numara **yazma anında** (Insert) alınır ve `NextNumber` ilerler; form açıl
|
|||
önizleme istenir. Bu yüzden iptal edilen bir kayıt numarayı tüketebilir — boşluksuz numara
|
||||
gerekiyorsa numarayı `InsertAfterCommand` ile SQL tarafında üret.
|
||||
|
||||
**SQL tarafında açılan belge.** Kaydı formun değil bir yordamın açtığı durumda (ör. `Prc_P_PurchaseRfqAward`
|
||||
kazanan teklif için sipariş açar) numara `EXEC Adm_P_SequenceNext N'{Name}', @TenantId, @No OUTPUT`
|
||||
(PG: `CALL public."Adm_P_SequenceNext"('{Name}', v_tenant, v_no)`) ile aynı numaratörden alınır; satırı
|
||||
kilitleyerek `NextNumber`'ı ilerletir ve `FormatTemplate`/`ResetPeriod`'u `Sequence.GetNextSequence` ile
|
||||
birebir aynı uygular. `MAX + 1` ya da elle birleştirilmiş numara yazılmaz.
|
||||
|
||||
### 9.10 Zamanlanmış işler — `BackgroundWorker` (`App.BackgroundWorkers.RecurringJobs`)
|
||||
|
||||
"Her gece şu prosedür çalışsın", "her 5 dakikada bildirim kuyruğu boşalsın" istekleri.
|
||||
|
|
@ -4742,7 +4884,7 @@ satır yazar, bildirim tipi `Manuel`'dir.
|
|||
**Seed:** `data/App.Notifications.{NotificationTemplates,NotificationTypes,NotificationRules}.json`
|
||||
(§9.15; seed bayrakları açık, `Order` ile tür → kural sırası). Üretilmiş bildirimler seed'lenmez.
|
||||
|
||||
Onay akışındaki **`Inform` düğümü e-posta gönderir** (MailQueue üzerinden); UI bildirimi
|
||||
Onay akışındaki **`Inform` düğümü e-posta gönderir** (gönderici ile senkron, kuyruk değil — §4.7); UI bildirimi
|
||||
istiyorsan ayrıca bir bildirim kuralı gerekir.
|
||||
|
||||
### 9.12 Raporlar (`App.Reports.*`)
|
||||
|
|
@ -4757,8 +4899,10 @@ Raporlama DevExpress XtraReports tabanlıdır ve iki katmanı vardır:
|
|||
Route'lar: görüntüleyici `/admin/reports/{report}/view/{id?}/{listFormCode?}`, tasarımcı
|
||||
`/admin/reports/{report}/design/{id?}/{listFormCode?}`.
|
||||
|
||||
- Her List ekranının araç çubuğundaki rapor aksiyonu `DynamicGrid` (TreeList'te `DynamicTree`)
|
||||
raporunu **o anki filtrelerle** açar; bunun için hiçbir tanım yapılmaz.
|
||||
- List ekranının araç çubuğundaki **Rapor › Liste** aksiyonu `DynamicGrid` (Tree'de `DynamicTree`)
|
||||
raporunu **o anki filtre, sıralama ve kolon genişlikleriyle** açar; `FilterRowJson.AllowUserUiFilterSave`
|
||||
(varsayılan `true`) açıkken Grid, Tree ve Card'da görünür, başka tanım gerekmez. Form sayfasındaki
|
||||
**Rapor › Form** `DynamicForm` üretir (alt formda yok).
|
||||
- Kendi düzeni istenen kayıt çıktısı (sertifika, taahhütname, teklif, iş emri) **`Raporlar`
|
||||
kategorisinde bir `DynamicReport` şablonudur**: `HtmlContent` A4'e basılan HTML'dir, ayrı bir
|
||||
`.repx` çizilmez. Kayıtsız görüntüleme `/admin/reports/DynamicReport/view/{ŞablonId}`
|
||||
|
|
@ -4972,7 +5116,7 @@ Kurallar:
|
|||
### 10.6 "Konfigürasyonla çözülemeyen iş mantığı"
|
||||
|
||||
Eksik olan bir **bileşen olayı/prop'u/küçük yeteneğiyse** bu reçete değil §7.3'teki not
|
||||
geçerlidir: var olan bileşene eklenir, yeni bileşen ya da Developer Kit ekranı üretilmez.
|
||||
geçerlidir: Core'dur, yalnızca "core sisteme ekle" komutuyla var olan bileşene eklenir (§0.8).
|
||||
|
||||
1. Önce gerçekten çözülemediğini göster: ListForm + SQL + Custom Endpoint neden yetmiyor,
|
||||
bir iki cümleyle yaz.
|
||||
|
|
@ -5023,7 +5167,7 @@ isteniyorsa geçilir.
|
|||
5. **Onay akışı** — §4.7'deki `WorkflowDto`. Tipik grafik:
|
||||
`Start → Compare (tutar eşiği) → Approval (yönetici) / Approval (üst yönetici) → Inform → End`.
|
||||
`ApprovalIsFilterUserName: true` ile herkes yalnızca kendi onayına düşenleri görür,
|
||||
`ApprovalIsResetWorkflow: true` ile kayıt güncellenince akış başa döner.
|
||||
`ApprovalIsResetWorkflow: true` ile toolbar'daki Workflow Reset düğmesi akışı başa alır.
|
||||
6. **Yetki** — wizard `App.Hr.AdvanceRequests` kökünü ve `.Create/.Update/.Delete/.Export/
|
||||
.Import/.Note` alt yetkilerini üretir. Onaylayanların rolüne kök + `.Update` verilir;
|
||||
talep sahiplerine kök + `.Create` yeter.
|
||||
|
|
@ -5095,10 +5239,8 @@ Prompt ile üretim yaptıysan ek olarak:
|
|||
(§0.6.5).
|
||||
- [ ] Görselden üretildiyse: platformda karşılığı olmayan öğeler ve yapılan varsayımlar
|
||||
(tablo/kolon adları, anahtar tipi, lookup kaynakları) açıkça bildirildi (§0.7.4).
|
||||
- [ ] Talebin hazır araçlarla karşılanamayan kısmı için **yeni bileşen üretilmedi**; var olan
|
||||
bileşene eklenen olay/prop/küçük yetenek tarifte yazıldı ve onaylandı (§7.3).
|
||||
- [ ] Bileşene ekleme yapıldıysa geriye dönük uyumlu: mevcut varsayılan/davranış değişmedi,
|
||||
`componentProps.json` + (olaysa) `DESIGNER_PRIMARY_EVENTS` + reference §10.9/§10.10
|
||||
güncellendi; `npm run typecheck` ve `npm run lint` temiz.
|
||||
- [ ] Çerçeve dışına çıkan hiçbir değişiklik onaysız yapılmadı (§0.8); çerçeve içinde
|
||||
yapılabilen her şey sorudan önce bitirildi.
|
||||
- [ ] "Core sisteme ekle" komutu olmadan `api/` ya da `ui/` altına yeni özellik yazılmadı (§0.8);
|
||||
çerçeve içinde karşılanamayan kısım son mesajda "Core gerektiren kısım" notu olarak bildirildi.
|
||||
- [ ] Komutla Core'a ekleme yapıldıysa yalnızca komuttaki değişiklik yapıldı, geriye dönük uyumlu
|
||||
(mevcut varsayılan/davranış değişmedi), envanter (`lowcode-reference` ilgili bölüm, bileşense
|
||||
§10.9/§10.10) güncellendi; `npm run typecheck` / `npm run lint` ya da `dotnet build` temiz.
|
||||
|
|
|
|||
17
README.md
17
README.md
|
|
@ -431,8 +431,10 @@ Aynı `ListForm` tanımı, aynı veri hattı üzerinden birden fazla görünüml
|
|||
`Grid` · `Pivot` · `Tree` · `Chart` · `Gantt` · `Scheduler` · `CardView` · `TodoBoard (Kanban)` ·
|
||||
`Widget Group`
|
||||
|
||||
Kullanıcı görünümler arasında geçiş yapabilir; grid durumu (sütun sırası, genişlik, filtre,
|
||||
gruplama) kullanıcı bazlı saklanır ve sıfırlanabilir.
|
||||
Kullanıcı görünümler arasında geçiş yapabilir (seçilen görünüm tarayıcıda saklanır); grid durumu
|
||||
(sütun sırası, genişlik, filtre, gruplama) toolbar'dan elle kaydedilir, sunucuda kullanıcı > rol > genel
|
||||
önceliğiyle saklanır ve sıfırlanabilir. Hazır toolbar/satır butonları ve URL parametreleri:
|
||||
`lowcode-reference.instructions.md` §5.8.
|
||||
|
||||
**TodoBoard artık bir Kanban panosudur:** kolonlar `TodoOptionJson` içindeki `statusExpr`
|
||||
değerlerinden üretilir, kartlar kolonlar arasında sürüklenerek durum değiştirir ve panodan yeni
|
||||
|
|
@ -598,8 +600,8 @@ bırakılırsa sunucu veritabanındaki değeri geri yazar. Böylece seed dosyas
|
|||
görünen adı taşır.
|
||||
|
||||
Dinamik liste ekranlarının route deseni `/admin/list/{ListFormCode}` biçimindedir; form
|
||||
görünümleri `/admin/form/{listFormCode}/:id`, grafik `/admin/chart/{listFormCode}`, pivot
|
||||
`/admin/pivot/{listFormCode}` yollarını kullanır.
|
||||
görünümleri `/admin/form/{listFormCode}/:id`, grafik `/admin/chart/{listFormCode}` yollarını kullanır;
|
||||
pivot ayrı bir route değil, liste ekranının `LayoutJson.Pivot` görünümüdür.
|
||||
|
||||
Var olan bir ekranı düzenlemek için `/admin/listform/edit/{listFormCode}` — tüm JSON
|
||||
yapılandırması sekmeli bir editörde yönetilir (Veritabanı, Sütunlar, Filtreler, Düzenleme,
|
||||
|
|
@ -626,10 +628,11 @@ kontrol `ListFormWizardAppService` üzerindedir.
|
|||
|
||||
**Veri (ekran içi)**
|
||||
|
||||
- **Dışa aktarma:** xlsx, csv, pdf (grid durumuna ve görünür sütunlara saygı duyar).
|
||||
- **Dışa aktarma:** Grid'de pdf ve xlsx, Pivot'ta xlsx (`ExportJson.Enabled` + `PermissionJson.E`; grid durumuna ve görünür sütunlara saygı duyar).
|
||||
- **İçe aktarma:** `components/importManager` altındaki dosya yükleme → önizleme → ilerleme →
|
||||
sonuç akışı; sonuçlar `ListFormImportLog` üzerinde satır bazında raporlanır. Şablon dosyası
|
||||
ekran tanımından üretilir.
|
||||
ekran tanımından üretilir (`.xlsx/.xls/.csv`, en çok 10 MB; yalnız INSERT, `Insert*Command` kancaları
|
||||
çalışır, `InsertServiceAddress` atlanır).
|
||||
|
||||
**Ekran tanımı (wizard seed paketi)**
|
||||
|
||||
|
|
@ -1268,7 +1271,7 @@ ekranın kendi ayrıntılı açıklamasını gösterir (`DescTr`/`DescEn`, `lowc
|
|||
| --- | --- | --- |
|
||||
| [App.Administration.md](configs/seeds/docs/modules/App.Administration.md) | Yönetim (`App.Administration`) | Tanımlamalar (Kontaklar: satış ve satınalmanın ortak müşteri/tedarikçi kartı ve sekmeleri, kontak etiketleri) |
|
||||
| [App.Hr.md](configs/seeds/docs/modules/App.Hr.md) | İnsan Kaynakları (`App.Hr`) | Tanımlamalar (dizin + genel tanımlar), Organizasyon ve Yetkinlik, Personel Kaydı (Kimlik › Kullanıcılar › detay), İşe Alım, Çalışma Takvimi ve Vardiyalar, İzin Yönetimi, Puantaj ve Devam Takibi, Sağlık Kartları, Eğitimler, Performans Yönetimi, Disiplin Dosyaları, Araçlar, Ziyaretçiler, Olay Günlüğü, Intranet |
|
||||
| [App.Prc.md](configs/seeds/docs/modules/App.Prc.md) | Satınalma (`App.Prc`) | Tanımlamalar (ödeme/teslimat koşulları, ödeme/teslim yöntemleri) |
|
||||
| [App.Prc.md](configs/seeds/docs/modules/App.Prc.md) | Satınalma (`App.Prc`) | Tanımlamalar (ödeme/teslimat koşulları, ödeme/teslim yöntemleri, red nedenleri) · Malzeme Talepleri · Siparişler (sözleşme, tedarikçi bazlı teklif talebi ihalesi + fiyat/termin kıyası, satınalma siparişi) |
|
||||
| [App.Inventory.md](configs/seeds/docs/modules/App.Inventory.md) | Envanter (`App.Inventory`) | Tanımlamalar (ürün kategorileri, nitelikler, ürünler ve varyantlar, reçeteler, reçete patlatma) |
|
||||
| [App.Production.md](configs/seeds/docs/modules/App.Production.md) | Üretim (`App.Production`) | Tanımlamalar (iş merkezi etiketleri, iş merkezleri, operasyonlar) |
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,15 @@ public class ValidationRuleDto
|
|||
/// </summary>
|
||||
public string ComparisonType { get; set; } = "";
|
||||
|
||||
//ComparisonTarget
|
||||
/// <summary> Kullanildigi turler: compare
|
||||
/// Ayni kayitta karsilastirilacak alanin adi (FieldName)
|
||||
/// </summary>
|
||||
public string ComparisonTarget { get; set; }
|
||||
|
||||
/// <summary> Kullanildigi turler: custom, async
|
||||
/// `eval` edilen JS fonksiyonu: `(e) => e.value > 0`; `e.data` kaydin tamamidir. async'te Promise donebilir
|
||||
/// </summary>
|
||||
public string ValidationCallback { get; set; }
|
||||
|
||||
/// <summary> Kullanildigi turler: pattern,
|
||||
/// Regex ifadesi alir
|
||||
|
|
|
|||
|
|
@ -89,8 +89,6 @@ public class SelectRequestDto
|
|||
/// <summary> Grid uzerinde kullanici tarafli bir degisiklik var mi
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool Chart { get; set; } = false;
|
||||
|
||||
public bool IsChanged()
|
||||
{
|
||||
if (!Sort.IsNullOrEmpty() ||
|
||||
|
|
|
|||
|
|
@ -209,10 +209,6 @@ public class ListFormSelectAppService : PlatformAppService, IListFormSelectAppSe
|
|||
{
|
||||
result.TotalCount = await dynamicDataRepository.ExecuteScalarAsync<int>(selectQueryManager.TotalCountQuery, connectionString, param);
|
||||
}
|
||||
else if (queryParams.Chart && !string.IsNullOrEmpty(selectQueryManager.ChartQuery))
|
||||
{
|
||||
result.Data = await dynamicDataRepository.QueryAsync(selectQueryManager.ChartQuery, connectionString, param);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Data = await dynamicDataRepository.QueryAsync(selectQueryManager.SelectQuery, connectionString, param);
|
||||
|
|
|
|||
|
|
@ -145,8 +145,9 @@ public sealed class EditorScriptRule
|
|||
if (json.TryGetProperty("conditions", out var more) && more.ValueKind == System.Text.Json.JsonValueKind.Array)
|
||||
conditions.AddRange(more.EnumerateArray().Select(Condition));
|
||||
|
||||
// Kosulsuz kural "always" ile yazilir; ToJson onu kendisi ekler.
|
||||
rule.AddConditions([.. conditions.Where(c => c.Operator != "always")], Text(json, "join") == "or");
|
||||
// Ek "always" kosullari dialogun basliginda durur; atilirsa ToJson farkli baslik uretir ve
|
||||
// script dialogda "elle duzenlenmis" sayilir. Tek "always" ise EffectiveConditions ile aynidir.
|
||||
rule.AddConditions([.. conditions], Text(json, "join") == "or");
|
||||
|
||||
return rule.WithTrigger(Text(json, "trigger") switch
|
||||
{
|
||||
|
|
@ -404,8 +405,11 @@ public sealed class EditorScriptRule
|
|||
|
||||
case "today":
|
||||
{
|
||||
// TS ile ayni: gun sayisi tam sayiya kirpilir (Math.trunc(Number(offset))).
|
||||
var offset = Param("offset");
|
||||
var parsed = int.TryParse(offset, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value) ? value : 0;
|
||||
var parsed = decimal.TryParse(offset, NumberStyles.Float, CultureInfo.InvariantCulture, out var value)
|
||||
? (int)decimal.Truncate(value)
|
||||
: 0;
|
||||
var start = parsed != 0
|
||||
? "new Date(Date.now() + " + parsed.ToString(CultureInfo.InvariantCulture) + " * 86400000)"
|
||||
: "new Date()";
|
||||
|
|
@ -459,7 +463,11 @@ public sealed class EditorScriptRule
|
|||
(Param("accuracy").Length > 0 ? ", " + q(Param("accuracy")) : string.Empty) + ")";
|
||||
|
||||
case "custom":
|
||||
return Param("code").Trim().TrimEnd(';');
|
||||
{
|
||||
// TS ile ayni: yalnizca sondaki tek ';' silinir.
|
||||
var code = Param("code").Trim();
|
||||
return code.EndsWith(';') ? code[..^1] : code;
|
||||
}
|
||||
|
||||
default:
|
||||
return string.Empty;
|
||||
|
|
|
|||
|
|
@ -1,126 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
using Volo.Abp.Domain.Values;
|
||||
|
||||
namespace Sozsoft.Platform.Queries;
|
||||
|
||||
public class ChartSeries : ValueObject
|
||||
{
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("ArgumentField")]
|
||||
public string ArgumentField { get; private set; } = "arg";
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("Axis")]
|
||||
public string Axis { get; private set; }
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("BarOverlapGroup")]
|
||||
public string BarOverlapGroup { get; private set; }
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("BarPadding")]
|
||||
public int BarPadding { get; private set; }
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("BarWidth")]
|
||||
public int BarWidth { get; private set; }
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("Color")]
|
||||
public string Color { get; private set; }
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("CornerRadius")]
|
||||
public int CornerRadius { get; private set; } = 0;
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("DashStyle")]
|
||||
public string DashStyle { get; private set; } = "solid";
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("IgnoreEmptyPoints")]
|
||||
public bool IgnoreEmptyPoints { get; private set; } = false;
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("Name")]
|
||||
public string Name { get; private set; }
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("Pane")]
|
||||
public string Pane { get; private set; }
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("RangeValue1Field")]
|
||||
public string RangeValue1Field { get; private set; } = "val1";
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("RangeValue2Field")]
|
||||
public string RangeValue2Field { get; private set; } = "val2";
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("SelectionMode")]
|
||||
public string SelectionMode { get; private set; } = "none";
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("ShowInLegend")]
|
||||
public bool ShowInLegend { get; private set; } = true;
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("Type")]
|
||||
public string Type { get; private set; }
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("ValueField")]
|
||||
public string ValueField { get; private set; }
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("SummaryType")]
|
||||
public string SummaryType { get; private set; }
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("Visible")]
|
||||
public bool Visible { get; private set; } = true;
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("Width")]
|
||||
public int Width { get; private set; } = 2;
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("Label")]
|
||||
public ChartLabel Label { get; private set; } = new();
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("UserId")]
|
||||
public string UserId { get; private set; }
|
||||
|
||||
// JSON + EF Core için parametresiz public ctor
|
||||
public ChartSeries() { }
|
||||
|
||||
protected override IEnumerable<object> GetAtomicValues()
|
||||
{
|
||||
yield return ArgumentField;
|
||||
yield return Axis;
|
||||
yield return BarOverlapGroup;
|
||||
yield return BarPadding;
|
||||
yield return BarWidth;
|
||||
yield return Color;
|
||||
yield return CornerRadius;
|
||||
yield return DashStyle;
|
||||
yield return IgnoreEmptyPoints;
|
||||
yield return Name;
|
||||
yield return Pane;
|
||||
yield return RangeValue1Field;
|
||||
yield return RangeValue2Field;
|
||||
yield return SelectionMode;
|
||||
yield return ShowInLegend;
|
||||
yield return Type;
|
||||
yield return ValueField;
|
||||
yield return SummaryType;
|
||||
yield return Visible;
|
||||
yield return Width;
|
||||
yield return Label;
|
||||
yield return UserId;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -99,23 +99,7 @@ public class DefaultValueManager : PlatformDomainService, IDefaultValueManager
|
|||
value = CurrentTenant.Id;
|
||||
else
|
||||
{
|
||||
if ((object)inputParams != null)
|
||||
{
|
||||
foreach (var item in JsonSerializer.Deserialize<Dictionary<string, object>>(inputParams))
|
||||
{
|
||||
var field = listFormFields.FirstOrDefault(c => c.FieldName == item.Key);
|
||||
if (field == null
|
||||
|| (op == OperationEnum.Insert && !field.CanCreate)
|
||||
|| (op == OperationEnum.Duplicate && !field.CanCreate)
|
||||
|| (op == OperationEnum.Update && !field.CanUpdate)
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
value = QueryHelper.GetFormattedValue(field.SourceDbType, item.Value);
|
||||
}
|
||||
}
|
||||
value = GetInputFieldValue(defaultField.Value, listFormFields, op, inputParams);
|
||||
}
|
||||
break;
|
||||
case FieldCustomValueTypeEnum.QueryParams:
|
||||
|
|
@ -170,5 +154,29 @@ public class DefaultValueManager : PlatformDomainService, IDefaultValueManager
|
|||
|
||||
return fields;
|
||||
}
|
||||
}
|
||||
|
||||
// "@Alan" gonderilen kaydin o alaninin degerini kopyalar. Tanimsiz token bir degere
|
||||
// dusmemeli: eslesmeyen ad null doner ve alan hic yazilmaz.
|
||||
private static object GetInputFieldValue(string token, List<ListFormField> listFormFields, OperationEnum op, dynamic inputParams)
|
||||
{
|
||||
if ((object)inputParams == null || string.IsNullOrWhiteSpace(token) || !token.StartsWith('@'))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var fieldName = token[1..];
|
||||
var field = listFormFields.FirstOrDefault(c => string.Equals(c.FieldName, fieldName, StringComparison.OrdinalIgnoreCase));
|
||||
if (field == null
|
||||
|| ((op == OperationEnum.Insert || op == OperationEnum.Duplicate) && !field.CanCreate)
|
||||
|| (op == OperationEnum.Update && !field.CanUpdate))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Dictionary<string, object> input = JsonSerializer.Deserialize<Dictionary<string, object>>(inputParams);
|
||||
var item = input?.FirstOrDefault(c => string.Equals(c.Key, field.FieldName, StringComparison.OrdinalIgnoreCase));
|
||||
return item is { Key: not null } entry
|
||||
? QueryHelper.GetFormattedValue(field.SourceDbType, entry.Value)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,9 +38,6 @@ public class QueryParameters : ValueObject
|
|||
//select
|
||||
//userData
|
||||
|
||||
//Chart
|
||||
public bool Chart { get; set; } = false;
|
||||
|
||||
protected override IEnumerable<object> GetAtomicValues()
|
||||
{
|
||||
yield return ListFormCode;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ public interface ISelectQueryManager
|
|||
Dictionary<string, object> SelectQueryParameters { get; }
|
||||
string TotalCountQuery { get; }
|
||||
string GroupQuery { get; }
|
||||
string ChartQuery { get; }
|
||||
public string DeleteQuery { get; }
|
||||
List<(int Index, string Field, string SelectExpr, string Sort, bool IsExpanded, string GroupInterval)> GroupTuples { get; }
|
||||
List<(int Index, string Field, string SelectExpr, string SummaryType)> GroupSummaryTuples { get; }
|
||||
|
|
@ -63,7 +62,7 @@ public class SelectField
|
|||
// JOIN bolumunde birden fazla condition var ise
|
||||
if (!string.IsNullOrEmpty(JoinOptions.JoinFieldName2))
|
||||
{
|
||||
JoinSql += $" {JoinOptions.JoinCondition2} \"{JoinOptions.JoinFieldName2}\" = {JoinOptions.BaseTableJoinFieldName2_OrValue}";
|
||||
JoinSql += $" {JoinOptions.JoinCondition2} {QuoteJoinField(JoinOptions.JoinFieldName2, JoinOptions.TableName)} = {JoinOptions.BaseTableJoinFieldName2_OrValue}";
|
||||
}
|
||||
|
||||
IsJoined = true;
|
||||
|
|
@ -75,6 +74,20 @@ public class SelectField
|
|||
}
|
||||
}
|
||||
|
||||
// "Tablo.Kolon" parcalari ayri ayri tirnaklanir; yalin kolon join tablosuna baglanir.
|
||||
private static string QuoteJoinField(string field, string joinTableName)
|
||||
{
|
||||
var parts = field.Split('.', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||
.Select(part => part.Trim('"', '[', ']'))
|
||||
.ToList();
|
||||
if (parts.Count == 1)
|
||||
{
|
||||
parts.Insert(0, joinTableName);
|
||||
}
|
||||
|
||||
return string.Join('.', parts.Select(part => $"\"{part}\""));
|
||||
}
|
||||
|
||||
public string FieldName { get; set; } // UserName
|
||||
public string SelectFieldName { get; set; } // ListForm.UserName as UserName
|
||||
public bool IsJoined { get; set; }
|
||||
|
|
@ -101,7 +114,6 @@ public class SelectQueryManager : PlatformDomainService, ISelectQueryManager
|
|||
public string TotalCountQuery { get; private set; }
|
||||
public string GroupQuery { get; private set; }
|
||||
public string DeleteQuery { get; private set; }
|
||||
public string ChartQuery { get; private set; }
|
||||
public List<(int Index, string Field, string SelectExpr, string Sort, bool IsExpanded, string GroupInterval)> GroupTuples { get; private set; } = [];
|
||||
public List<(int Index, string Field, string SelectExpr, string SummaryType)> GroupSummaryTuples { get; private set; } = [];
|
||||
public List<string> SummaryQueries { get; private set; }
|
||||
|
|
@ -196,7 +208,6 @@ public class SelectQueryManager : PlatformDomainService, ISelectQueryManager
|
|||
TotalCountQuery = GetTotalCountQuery();
|
||||
GroupQuery = GetGroupQuery(listFormFields, queryParams);
|
||||
DeleteQuery = GetDeleteQuery(queryParams);
|
||||
ChartQuery = GetChartQuery(listform, queryParams);
|
||||
|
||||
#region Total Summary Queries
|
||||
if (queryParams != null && !queryParams.TotalSummary.IsNullOrWhiteSpace())
|
||||
|
|
@ -239,7 +250,6 @@ public class SelectQueryManager : PlatformDomainService, ISelectQueryManager
|
|||
TotalCountQuery = null;
|
||||
GroupQuery = null;
|
||||
DeleteQuery = null;
|
||||
ChartQuery = null;
|
||||
GroupTuples = [];
|
||||
GroupSummaryTuples = [];
|
||||
SummaryQueries = [];
|
||||
|
|
@ -982,58 +992,9 @@ public class SelectQueryManager : PlatformDomainService, ISelectQueryManager
|
|||
if (queryParams == null || queryParams.CreateDeleteQuery == false)
|
||||
return null;
|
||||
|
||||
return $"DELETE \"{TableName}\" FROM {SelectCommand} AS \"{TableName}\" {GetWhereString()}";
|
||||
}
|
||||
|
||||
public string GetChartQuery(ListForm listform, QueryParameters queryParams = null)
|
||||
{
|
||||
if (listform == null || string.IsNullOrWhiteSpace(listform.SeriesJson) || queryParams == null)
|
||||
return null;
|
||||
|
||||
var seriesList = JsonSerializer.Deserialize<List<ChartSeries>>(listform.SeriesJson);
|
||||
|
||||
if (seriesList == null || seriesList.Count == 0)
|
||||
return null;
|
||||
|
||||
// ArgumentField listesi
|
||||
var argumentFields = seriesList.Select(s => s.ArgumentField).Distinct().ToList();
|
||||
|
||||
// ArgumentField ifadesini oluştur
|
||||
string argumentExpression;
|
||||
if (argumentFields.Count == 1)
|
||||
{
|
||||
// Tek ArgumentField
|
||||
argumentExpression = $"[{argumentFields.First()}]";
|
||||
}
|
||||
else
|
||||
{
|
||||
argumentExpression = string.Join(PlatformConsts.MultiValueDelimiter, argumentFields.Select(f => $"[{f}]"));
|
||||
}
|
||||
|
||||
// Select sütunlarını oluştur
|
||||
var selectParts = new List<string> { $"{argumentExpression} AS ArgumentField" };
|
||||
foreach (var series in seriesList)
|
||||
{
|
||||
string sqlFunc = series.SummaryType.ToUpper() switch
|
||||
{
|
||||
"COUNT" => $"COUNT([{series.ValueField}])",
|
||||
"SUM" => $"SUM([{series.ValueField}])",
|
||||
"AVG" => $"AVG([{series.ValueField}])",
|
||||
"MIN" => $"MIN([{series.ValueField}])",
|
||||
"MAX" => $"MAX([{series.ValueField}])",
|
||||
_ => throw new NotSupportedException($"Unsupported SummaryType: {series.SummaryType}")
|
||||
};
|
||||
|
||||
selectParts.Add($"{sqlFunc} AS [{series.Name}]");
|
||||
}
|
||||
|
||||
// SQL cümlesi
|
||||
var sql = $@"
|
||||
SELECT {string.Join(", ", selectParts)}
|
||||
FROM [{listform.SelectCommand}] AS ""{TableName}""
|
||||
{GetWhereString()}
|
||||
GROUP BY {argumentExpression}";
|
||||
|
||||
return sql;
|
||||
// PostgreSQL "DELETE alias FROM" sozdizimini tanimaz; alias'i hedef tablonun kendisine verir.
|
||||
return DataSourceType == DataSourceTypeEnum.Postgresql
|
||||
? $"DELETE FROM {SelectCommand} AS \"{TableName}\" {GetWhereString()}"
|
||||
: $"DELETE \"{TableName}\" FROM {SelectCommand} AS \"{TableName}\" {GetWhereString()}";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
31
claude.md
31
claude.md
|
|
@ -48,13 +48,13 @@ options you rejected.
|
|||
3. Every implementation proposal must include tenant and permission design.
|
||||
4. Never bypass platform authorization patterns.
|
||||
5. Never hardcode secrets, tenant IDs, or connection strings.
|
||||
6. Never step outside the framework without explicit approval (standing default 11).
|
||||
6. Never add a new Core feature (`api/`, `ui/` code) without the command "core sisteme ekle" (standing default 11).
|
||||
|
||||
Exception:
|
||||
|
||||
- Custom React/backend code is allowed only when the user explicitly requests implementation
|
||||
and configuration is insufficient.
|
||||
- In such cases, explain why configuration-first options are not enough — in a sentence or two.
|
||||
- Custom React/backend code is written only on the user's command ("core sisteme ekle" or a
|
||||
request that names the code change) — never because configuration seemed insufficient.
|
||||
- When Core would be needed, say why the ListForm inventory is not enough — in a sentence or two.
|
||||
|
||||
## Architecture Guardrails
|
||||
|
||||
|
|
@ -160,14 +160,17 @@ Bir çelişki varsa sıra: `ai.instructions.md` → `dotnet.instructions.md` →
|
|||
`EditorOptions`; kod yazmak son çare.
|
||||
9. **SQL** → her zaman parametreli. String birleştirme ile sorgu kurma.
|
||||
10. **Silme** → `DeleteCommand = DefaultDeleteCommand("{Tablo}")`; ham SQL string'i yazma.
|
||||
11. **Çerçeve sınırı** → uygulama kendini kendi mekanizmalarıyla geliştirir (seed artefaktları;
|
||||
var olan `ui` bileşenine eksik olay/prop/küçük yetenek ekleme — komponentin %70'i hazır
|
||||
araçlarla kuruluyorsa kalanı bu eklemelerle tamamlanır, yeni bileşen yazılmaz; geriye dönük
|
||||
uyumlu tarif/seçenek/token ekleme).
|
||||
Bunun dışına çıkan her şey — yeni React bileşeni/sayfası, çekirdek motor, yeni entity/
|
||||
migration, platform tablosu şeması, yeni paket, `Routes`, dış entegrasyon — **önce sorulur,
|
||||
yalnızca onayla yapılır**; onay talebe özeldir. Çerçeve içinde yapılabilen kısım sorudan önce
|
||||
bitirilir. "Yapılamaz" cevabı yoktur. Listeler: `lowcode.instructions.md` §0.8.
|
||||
11. **Core'a yeni özellik yalnızca komutla** → Core = `api/` + `ui/` kaynak kodu; çerçeve =
|
||||
`configs/seeds/` artefaktları. Kullanıcı **"core sisteme ekle"** (ya da Core değişikliğini adıyla
|
||||
isteyen eşdeğer komut) demedikçe Core'a yeni özellik yazılmaz — küçük/geriye dönük uyumlu olması
|
||||
fark etmez: DTO alanı, var olan bileşene prop/olay, tarif, `EditorOptions` anahtarı, token, yeni
|
||||
React bileşeni/sayfası, çekirdek motor, entity/migration, platform tablosu şeması, paket,
|
||||
`Routes`, dış entegrasyon. "Core gerekiyor" demeden önce ListForm'un bütün yetenekleri taranır
|
||||
(`lowcode-reference.instructions.md` §0–§9, `lowcode` §4–§9). Komut yoksa çerçeve içindeki kısım
|
||||
bitirilir, son mesajda tek bir "Core gerektiren kısım" notu yazılır (soru kutusuyla Core önerilmez).
|
||||
Bildirilen hatanın yeni ayar eklemeden düzeltilmesi yeni özellik değildir. Komut yalnızca adı
|
||||
geçen değişikliği kapsar, sonraki talebe taşınmaz; eklenen yetenek envantere yazılır. "Yapılamaz"
|
||||
cevabı yoktur. Ayrıntı: `lowcode.instructions.md` §0.8.
|
||||
12. **Liste ekranı görünümleri** → prompt/görsel/tarifle üretilen her liste ekranı `Grid` + `Card` +
|
||||
`Pivot` + `Chart` açık, `DefaultLayout: "grid"` ile gelir; "liste/grid" demek diğerlerini
|
||||
kapatmak değildir. Bir görünüm yalnızca istek onu açıkça dışarıda bıraktığında `false` yazılır.
|
||||
|
|
@ -278,6 +281,10 @@ Bir çelişki varsa sıra: `ai.instructions.md` → `dotnet.instructions.md` →
|
|||
- **`phoneFormat.ts` ↔ `DynamicReportPhoneFormatter.cs`** — telefon token'larının (`phoneGlobal`, `phoneTR`,
|
||||
`phoneIntl`, `phoneCountry`) görüntü kuralı iki yerde yazılır: liste/kart istemcide, dinamik rapor sunucuda.
|
||||
Biri değişirse diğeri de değişir; yoksa liste ile rapor aynı numarayı farklı yazar.
|
||||
- **`Sequence.GetNextSequence` (C#) ↔ `Adm_P_SequenceNext.sql` (SQL Server + PG)** — numaratörün biçim
|
||||
(`FormatTemplate` token'ları, `PaddingSize`) ve sıfırlama (`ResetPeriod`/`LastPeriodKey`) kuralı iki yerde yazılır:
|
||||
formdan açılan kayıt C#'tan, yordamın açtığı belge (tekliften sipariş, alternatif teklif) SQL'den numara alır.
|
||||
Biri değişirse diğeri de değişir; yoksa aynı numaratör iki farklı biçimde numara üretir.
|
||||
- **Liste popup'ı (Grid/Tree) ↔ form sayfası (`FormDevExpress`)** — editör yetenekleri ortak yardımcılardadır
|
||||
(`list/shared/editingForm.ts`, `editingFormScripts.ts`, `cascade.ts`); TagBox/GridBox/ImageUpload/ImageViewer/Rating'in
|
||||
tek uygulaması `form/editors/*`, liste hücresi yalnızca `list/editors/cellEditors.tsx` adaptörüdür. Bir tarafa
|
||||
|
|
|
|||
|
|
@ -17044,286 +17044,6 @@
|
|||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderLine",
|
||||
"ParentName": "App.Prc.PurchaseRfq",
|
||||
"DisplayName": "App.Prc.PurchaseOrderLine",
|
||||
"Order": 7,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderLine.Create",
|
||||
"ParentName": "App.Prc.PurchaseOrderLine",
|
||||
"DisplayName": "App.Platform.Create",
|
||||
"Order": 1,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderLine.Update",
|
||||
"ParentName": "App.Prc.PurchaseOrderLine",
|
||||
"DisplayName": "App.Platform.Update",
|
||||
"Order": 2,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderLine.Delete",
|
||||
"ParentName": "App.Prc.PurchaseOrderLine",
|
||||
"DisplayName": "App.Platform.Delete",
|
||||
"Order": 3,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderLine.Export",
|
||||
"ParentName": "App.Prc.PurchaseOrderLine",
|
||||
"DisplayName": "App.Platform.Export",
|
||||
"Order": 4,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderLine.Import",
|
||||
"ParentName": "App.Prc.PurchaseOrderLine",
|
||||
"DisplayName": "App.Platform.Import",
|
||||
"Order": 5,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderLine.Note",
|
||||
"ParentName": "App.Prc.PurchaseOrderLine",
|
||||
"DisplayName": "App.Platform.Note",
|
||||
"Order": 6,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderQuote",
|
||||
"ParentName": "App.Prc.PurchaseRfq",
|
||||
"DisplayName": "App.Prc.PurchaseOrderQuote",
|
||||
"Order": 8,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderQuote.Create",
|
||||
"ParentName": "App.Prc.PurchaseOrderQuote",
|
||||
"DisplayName": "App.Platform.Create",
|
||||
"Order": 1,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderQuote.Update",
|
||||
"ParentName": "App.Prc.PurchaseOrderQuote",
|
||||
"DisplayName": "App.Platform.Update",
|
||||
"Order": 2,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderQuote.Delete",
|
||||
"ParentName": "App.Prc.PurchaseOrderQuote",
|
||||
"DisplayName": "App.Platform.Delete",
|
||||
"Order": 3,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderQuote.Export",
|
||||
"ParentName": "App.Prc.PurchaseOrderQuote",
|
||||
"DisplayName": "App.Platform.Export",
|
||||
"Order": 4,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderQuote.Import",
|
||||
"ParentName": "App.Prc.PurchaseOrderQuote",
|
||||
"DisplayName": "App.Platform.Import",
|
||||
"Order": 5,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderQuote.Note",
|
||||
"ParentName": "App.Prc.PurchaseOrderQuote",
|
||||
"DisplayName": "App.Platform.Note",
|
||||
"Order": 6,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderOther",
|
||||
"ParentName": "App.Prc.PurchaseRfq",
|
||||
"DisplayName": "App.Prc.PurchaseOrderOther",
|
||||
"Order": 9,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderOther.Create",
|
||||
"ParentName": "App.Prc.PurchaseOrderOther",
|
||||
"DisplayName": "App.Platform.Create",
|
||||
"Order": 1,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderOther.Update",
|
||||
"ParentName": "App.Prc.PurchaseOrderOther",
|
||||
"DisplayName": "App.Platform.Update",
|
||||
"Order": 2,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderOther.Delete",
|
||||
"ParentName": "App.Prc.PurchaseOrderOther",
|
||||
"DisplayName": "App.Platform.Delete",
|
||||
"Order": 3,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderOther.Export",
|
||||
"ParentName": "App.Prc.PurchaseOrderOther",
|
||||
"DisplayName": "App.Platform.Export",
|
||||
"Order": 4,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderOther.Import",
|
||||
"ParentName": "App.Prc.PurchaseOrderOther",
|
||||
"DisplayName": "App.Platform.Import",
|
||||
"Order": 5,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderOther.Note",
|
||||
"ParentName": "App.Prc.PurchaseOrderOther",
|
||||
"DisplayName": "App.Platform.Note",
|
||||
"Order": 6,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderAlternative",
|
||||
"ParentName": "App.Prc.PurchaseRfq",
|
||||
"DisplayName": "App.Prc.PurchaseOrderAlternative",
|
||||
"Order": 10,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderAlternative.Create",
|
||||
"ParentName": "App.Prc.PurchaseOrderAlternative",
|
||||
"DisplayName": "App.Platform.Create",
|
||||
"Order": 1,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderAlternative.Update",
|
||||
"ParentName": "App.Prc.PurchaseOrderAlternative",
|
||||
"DisplayName": "App.Platform.Update",
|
||||
"Order": 2,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderAlternative.Delete",
|
||||
"ParentName": "App.Prc.PurchaseOrderAlternative",
|
||||
"DisplayName": "App.Platform.Delete",
|
||||
"Order": 3,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderAlternative.Export",
|
||||
"ParentName": "App.Prc.PurchaseOrderAlternative",
|
||||
"DisplayName": "App.Platform.Export",
|
||||
"Order": 4,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderAlternative.Import",
|
||||
"ParentName": "App.Prc.PurchaseOrderAlternative",
|
||||
"DisplayName": "App.Platform.Import",
|
||||
"Order": 5,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderAlternative.Note",
|
||||
"ParentName": "App.Prc.PurchaseOrderAlternative",
|
||||
"DisplayName": "App.Platform.Note",
|
||||
"Order": 6,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfq",
|
||||
|
|
@ -17394,6 +17114,426 @@
|
|||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqLine",
|
||||
"ParentName": "App.Prc.PurchaseRfq",
|
||||
"DisplayName": "App.Prc.PurchaseRfqLine",
|
||||
"Order": 7,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqLine.Create",
|
||||
"ParentName": "App.Prc.PurchaseRfqLine",
|
||||
"DisplayName": "App.Platform.Create",
|
||||
"Order": 1,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqLine.Update",
|
||||
"ParentName": "App.Prc.PurchaseRfqLine",
|
||||
"DisplayName": "App.Platform.Update",
|
||||
"Order": 2,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqLine.Delete",
|
||||
"ParentName": "App.Prc.PurchaseRfqLine",
|
||||
"DisplayName": "App.Platform.Delete",
|
||||
"Order": 3,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqLine.Export",
|
||||
"ParentName": "App.Prc.PurchaseRfqLine",
|
||||
"DisplayName": "App.Platform.Export",
|
||||
"Order": 4,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqLine.Import",
|
||||
"ParentName": "App.Prc.PurchaseRfqLine",
|
||||
"DisplayName": "App.Platform.Import",
|
||||
"Order": 5,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqLine.Note",
|
||||
"ParentName": "App.Prc.PurchaseRfqLine",
|
||||
"DisplayName": "App.Platform.Note",
|
||||
"Order": 6,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqImportItem",
|
||||
"ParentName": "App.Prc.PurchaseRfq",
|
||||
"DisplayName": "App.Prc.PurchaseRfqImportItem",
|
||||
"Order": 8,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqImportItem.Create",
|
||||
"ParentName": "App.Prc.PurchaseRfqImportItem",
|
||||
"DisplayName": "App.Platform.Create",
|
||||
"Order": 1,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqImportItem.Update",
|
||||
"ParentName": "App.Prc.PurchaseRfqImportItem",
|
||||
"DisplayName": "App.Platform.Update",
|
||||
"Order": 2,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqImportItem.Delete",
|
||||
"ParentName": "App.Prc.PurchaseRfqImportItem",
|
||||
"DisplayName": "App.Platform.Delete",
|
||||
"Order": 3,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqImportItem.Export",
|
||||
"ParentName": "App.Prc.PurchaseRfqImportItem",
|
||||
"DisplayName": "App.Platform.Export",
|
||||
"Order": 4,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqImportItem.Import",
|
||||
"ParentName": "App.Prc.PurchaseRfqImportItem",
|
||||
"DisplayName": "App.Platform.Import",
|
||||
"Order": 5,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqImportItem.Note",
|
||||
"ParentName": "App.Prc.PurchaseRfqImportItem",
|
||||
"DisplayName": "App.Platform.Note",
|
||||
"Order": 6,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqQuote",
|
||||
"ParentName": "App.Prc.PurchaseRfq",
|
||||
"DisplayName": "App.Prc.PurchaseRfqQuote",
|
||||
"Order": 9,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqQuote.Create",
|
||||
"ParentName": "App.Prc.PurchaseRfqQuote",
|
||||
"DisplayName": "App.Platform.Create",
|
||||
"Order": 1,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqQuote.Update",
|
||||
"ParentName": "App.Prc.PurchaseRfqQuote",
|
||||
"DisplayName": "App.Platform.Update",
|
||||
"Order": 2,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqQuote.Delete",
|
||||
"ParentName": "App.Prc.PurchaseRfqQuote",
|
||||
"DisplayName": "App.Platform.Delete",
|
||||
"Order": 3,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqQuote.Export",
|
||||
"ParentName": "App.Prc.PurchaseRfqQuote",
|
||||
"DisplayName": "App.Platform.Export",
|
||||
"Order": 4,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqQuote.Import",
|
||||
"ParentName": "App.Prc.PurchaseRfqQuote",
|
||||
"DisplayName": "App.Platform.Import",
|
||||
"Order": 5,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqQuote.Note",
|
||||
"ParentName": "App.Prc.PurchaseRfqQuote",
|
||||
"DisplayName": "App.Platform.Note",
|
||||
"Order": 6,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqOther",
|
||||
"ParentName": "App.Prc.PurchaseRfq",
|
||||
"DisplayName": "App.Prc.PurchaseRfqOther",
|
||||
"Order": 10,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqOther.Create",
|
||||
"ParentName": "App.Prc.PurchaseRfqOther",
|
||||
"DisplayName": "App.Platform.Create",
|
||||
"Order": 1,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqOther.Update",
|
||||
"ParentName": "App.Prc.PurchaseRfqOther",
|
||||
"DisplayName": "App.Platform.Update",
|
||||
"Order": 2,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqOther.Delete",
|
||||
"ParentName": "App.Prc.PurchaseRfqOther",
|
||||
"DisplayName": "App.Platform.Delete",
|
||||
"Order": 3,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqOther.Export",
|
||||
"ParentName": "App.Prc.PurchaseRfqOther",
|
||||
"DisplayName": "App.Platform.Export",
|
||||
"Order": 4,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqOther.Import",
|
||||
"ParentName": "App.Prc.PurchaseRfqOther",
|
||||
"DisplayName": "App.Platform.Import",
|
||||
"Order": 5,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqOther.Note",
|
||||
"ParentName": "App.Prc.PurchaseRfqOther",
|
||||
"DisplayName": "App.Platform.Note",
|
||||
"Order": 6,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqAlternative",
|
||||
"ParentName": "App.Prc.PurchaseRfq",
|
||||
"DisplayName": "App.Prc.PurchaseRfqAlternative",
|
||||
"Order": 11,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqAlternative.Create",
|
||||
"ParentName": "App.Prc.PurchaseRfqAlternative",
|
||||
"DisplayName": "App.Platform.Create",
|
||||
"Order": 1,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqAlternative.Update",
|
||||
"ParentName": "App.Prc.PurchaseRfqAlternative",
|
||||
"DisplayName": "App.Platform.Update",
|
||||
"Order": 2,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqAlternative.Delete",
|
||||
"ParentName": "App.Prc.PurchaseRfqAlternative",
|
||||
"DisplayName": "App.Platform.Delete",
|
||||
"Order": 3,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqAlternative.Export",
|
||||
"ParentName": "App.Prc.PurchaseRfqAlternative",
|
||||
"DisplayName": "App.Platform.Export",
|
||||
"Order": 4,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqAlternative.Import",
|
||||
"ParentName": "App.Prc.PurchaseRfqAlternative",
|
||||
"DisplayName": "App.Platform.Import",
|
||||
"Order": 5,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqAlternative.Note",
|
||||
"ParentName": "App.Prc.PurchaseRfqAlternative",
|
||||
"DisplayName": "App.Platform.Note",
|
||||
"Order": 6,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqComparison",
|
||||
"ParentName": "App.Prc.PurchaseRfq",
|
||||
"DisplayName": "App.Prc.PurchaseRfqComparison",
|
||||
"Order": 12,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqComparison.Create",
|
||||
"ParentName": "App.Prc.PurchaseRfqComparison",
|
||||
"DisplayName": "App.Platform.Create",
|
||||
"Order": 1,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqComparison.Update",
|
||||
"ParentName": "App.Prc.PurchaseRfqComparison",
|
||||
"DisplayName": "App.Platform.Update",
|
||||
"Order": 2,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqComparison.Delete",
|
||||
"ParentName": "App.Prc.PurchaseRfqComparison",
|
||||
"DisplayName": "App.Platform.Delete",
|
||||
"Order": 3,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqComparison.Export",
|
||||
"ParentName": "App.Prc.PurchaseRfqComparison",
|
||||
"DisplayName": "App.Platform.Export",
|
||||
"Order": 4,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqComparison.Import",
|
||||
"ParentName": "App.Prc.PurchaseRfqComparison",
|
||||
"DisplayName": "App.Platform.Import",
|
||||
"Order": 5,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseRfqComparison.Note",
|
||||
"ParentName": "App.Prc.PurchaseRfqComparison",
|
||||
"DisplayName": "App.Platform.Note",
|
||||
"Order": 6,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrder",
|
||||
|
|
@ -17463,6 +17603,286 @@
|
|||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderLine",
|
||||
"ParentName": "App.Prc.PurchaseOrder",
|
||||
"DisplayName": "App.Prc.PurchaseOrderLine",
|
||||
"Order": 7,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderLine.Create",
|
||||
"ParentName": "App.Prc.PurchaseOrderLine",
|
||||
"DisplayName": "App.Platform.Create",
|
||||
"Order": 1,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderLine.Update",
|
||||
"ParentName": "App.Prc.PurchaseOrderLine",
|
||||
"DisplayName": "App.Platform.Update",
|
||||
"Order": 2,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderLine.Delete",
|
||||
"ParentName": "App.Prc.PurchaseOrderLine",
|
||||
"DisplayName": "App.Platform.Delete",
|
||||
"Order": 3,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderLine.Export",
|
||||
"ParentName": "App.Prc.PurchaseOrderLine",
|
||||
"DisplayName": "App.Platform.Export",
|
||||
"Order": 4,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderLine.Import",
|
||||
"ParentName": "App.Prc.PurchaseOrderLine",
|
||||
"DisplayName": "App.Platform.Import",
|
||||
"Order": 5,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderLine.Note",
|
||||
"ParentName": "App.Prc.PurchaseOrderLine",
|
||||
"DisplayName": "App.Platform.Note",
|
||||
"Order": 6,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderImportItem",
|
||||
"ParentName": "App.Prc.PurchaseOrder",
|
||||
"DisplayName": "App.Prc.PurchaseOrderImportItem",
|
||||
"Order": 8,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderImportItem.Create",
|
||||
"ParentName": "App.Prc.PurchaseOrderImportItem",
|
||||
"DisplayName": "App.Platform.Create",
|
||||
"Order": 1,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderImportItem.Update",
|
||||
"ParentName": "App.Prc.PurchaseOrderImportItem",
|
||||
"DisplayName": "App.Platform.Update",
|
||||
"Order": 2,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderImportItem.Delete",
|
||||
"ParentName": "App.Prc.PurchaseOrderImportItem",
|
||||
"DisplayName": "App.Platform.Delete",
|
||||
"Order": 3,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderImportItem.Export",
|
||||
"ParentName": "App.Prc.PurchaseOrderImportItem",
|
||||
"DisplayName": "App.Platform.Export",
|
||||
"Order": 4,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderImportItem.Import",
|
||||
"ParentName": "App.Prc.PurchaseOrderImportItem",
|
||||
"DisplayName": "App.Platform.Import",
|
||||
"Order": 5,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderImportItem.Note",
|
||||
"ParentName": "App.Prc.PurchaseOrderImportItem",
|
||||
"DisplayName": "App.Platform.Note",
|
||||
"Order": 6,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderOther",
|
||||
"ParentName": "App.Prc.PurchaseOrder",
|
||||
"DisplayName": "App.Prc.PurchaseOrderOther",
|
||||
"Order": 9,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderOther.Create",
|
||||
"ParentName": "App.Prc.PurchaseOrderOther",
|
||||
"DisplayName": "App.Platform.Create",
|
||||
"Order": 1,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderOther.Update",
|
||||
"ParentName": "App.Prc.PurchaseOrderOther",
|
||||
"DisplayName": "App.Platform.Update",
|
||||
"Order": 2,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderOther.Delete",
|
||||
"ParentName": "App.Prc.PurchaseOrderOther",
|
||||
"DisplayName": "App.Platform.Delete",
|
||||
"Order": 3,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderOther.Export",
|
||||
"ParentName": "App.Prc.PurchaseOrderOther",
|
||||
"DisplayName": "App.Platform.Export",
|
||||
"Order": 4,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderOther.Import",
|
||||
"ParentName": "App.Prc.PurchaseOrderOther",
|
||||
"DisplayName": "App.Platform.Import",
|
||||
"Order": 5,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderOther.Note",
|
||||
"ParentName": "App.Prc.PurchaseOrderOther",
|
||||
"DisplayName": "App.Platform.Note",
|
||||
"Order": 6,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderAlternative",
|
||||
"ParentName": "App.Prc.PurchaseOrder",
|
||||
"DisplayName": "App.Prc.PurchaseOrderAlternative",
|
||||
"Order": 10,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderAlternative.Create",
|
||||
"ParentName": "App.Prc.PurchaseOrderAlternative",
|
||||
"DisplayName": "App.Platform.Create",
|
||||
"Order": 1,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderAlternative.Update",
|
||||
"ParentName": "App.Prc.PurchaseOrderAlternative",
|
||||
"DisplayName": "App.Platform.Update",
|
||||
"Order": 2,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderAlternative.Delete",
|
||||
"ParentName": "App.Prc.PurchaseOrderAlternative",
|
||||
"DisplayName": "App.Platform.Delete",
|
||||
"Order": 3,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderAlternative.Export",
|
||||
"ParentName": "App.Prc.PurchaseOrderAlternative",
|
||||
"DisplayName": "App.Platform.Export",
|
||||
"Order": 4,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderAlternative.Import",
|
||||
"ParentName": "App.Prc.PurchaseOrderAlternative",
|
||||
"DisplayName": "App.Platform.Import",
|
||||
"Order": 5,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
},
|
||||
{
|
||||
"GroupName": "App.Prc",
|
||||
"Name": "App.Prc.PurchaseOrderAlternative.Note",
|
||||
"ParentName": "App.Prc.PurchaseOrderAlternative",
|
||||
"DisplayName": "App.Platform.Note",
|
||||
"Order": 6,
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3,
|
||||
"Modules": "Prc"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
"Id": "db014b58-ec8b-4a65-b406-078f66323b7c",
|
||||
"DepartmentId": "8f14e45f-ea2d-4d9f-9f1d-1a2b3c4d5e6f",
|
||||
"ApprovalArea": "Purchase",
|
||||
"ApproverUserId": "0b221f19-f587-b053-d903-3a24394b182b",
|
||||
"ApproverUserId": "9e2ef88f-7f14-8397-7963-3a243e534333",
|
||||
"IsActive": true
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -86,6 +86,20 @@
|
|||
"StartNumber": 1,
|
||||
"LastPeriodKey": null,
|
||||
"FormatTemplate": "{Prefix}{Number}{Suffix}"
|
||||
},
|
||||
{
|
||||
"Id": "d1287271-43f1-514d-96f2-f786c467eae9",
|
||||
"Name": "PurchaseRfq",
|
||||
"Prefix": "RFQ",
|
||||
"Suffix": "",
|
||||
"IsActive": true,
|
||||
"PaddingSize": 5,
|
||||
"IncrementStep": 1,
|
||||
"NextNumber": 1,
|
||||
"ResetPeriod": 0,
|
||||
"StartNumber": 1,
|
||||
"LastPeriodKey": null,
|
||||
"FormatTemplate": "{Prefix}{Number}{Suffix}"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31978,7 +31978,7 @@
|
|||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.BeforeSp",
|
||||
"Value": "Before Sp"
|
||||
"Value": "Önceki Stored Procedure"
|
||||
},
|
||||
{
|
||||
"Id": "cce778ab-fa38-5390-b7fd-430e7f2e9dab",
|
||||
|
|
@ -94257,14 +94257,14 @@
|
|||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderLine.Desc",
|
||||
"Value": "Order Lines — the products of a request for quotation or purchase order.\nWhere: Purchasing › Orders › Requests for Quotation and Purchase Orders › Products tab (no menu of its own).\nFields: product, description (from the product's purchase description), quantity, unit, unit price, tax rate (from the product's purchase tax rate), amount (quantity × unit price, calculated), material request line (filled by Import from Request, read-only).\nRules: lines cannot be added or deleted on a cancelled document; after every change the document's untaxed amount, tax and total are recalculated."
|
||||
"Value": "Order Lines — the products of a purchase order.\nWhere: Purchasing › Orders › Purchase Orders › Products tab (no menu of its own).\nFields: product, description, quantity, unit, unit price, tax rate, amount (quantity × unit price, calculated), delivery date, material request line (read-only).\nRules: lines of a cancelled order cannot be changed; after every change the order totals are recalculated. Lines of an order converted from an RFQ come from the winning RFQ lines."
|
||||
},
|
||||
{
|
||||
"Id": "9a9405ac-9609-55a4-a23a-6d470daedae0",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderLine.Desc",
|
||||
"Value": "Sipariş Kalemleri — teklif talebinin ya da satınalma siparişinin ürünleri.\nNerede: Satınalma › Siparişler › Teklif Talepleri ve Satınalma Siparişleri › Ürünler sekmesi (kendi menüsü yoktur).\nAlanlar: ürün, açıklama (ürünün satınalma açıklamasından), miktar, birim, birim fiyat, vergi oranı (ürünün satınalma vergisinden), tutar (miktar × birim fiyat, hesaplanır), talep kalemi (Talepten Aktar ile dolar, salt okunur).\nKurallar: iptal edilmiş belgeye kalem eklenemez ve silinemez; her değişiklikte belgenin vergi hariç tutarı, KDV'si ve toplamı yeniden hesaplanır."
|
||||
"Value": "Sipariş Kalemleri — satınalma siparişinin ürünleri.\nNerede: Satınalma › Siparişler › Satınalma Siparişleri › Ürünler sekmesi (kendi menüsü yoktur).\nAlanlar: ürün, açıklama, miktar, birim, birim fiyat, vergi oranı, tutar (miktar × birim fiyat, hesaplanır), teslim tarihi, talep kalemi (salt okunur).\nKurallar: iptal edilmiş siparişin kalemi değiştirilemez; her değişiklikte sipariş toplamları yeniden hesaplanır. Teklif talebinden dönüştürülen siparişin kalemleri kazanan teklif kalemlerinden gelir."
|
||||
},
|
||||
{
|
||||
"Id": "a7e229db-465a-5305-9150-3e2ae525853d",
|
||||
|
|
@ -94280,48 +94280,6 @@
|
|||
"Key": "App.Listform.ListformField.MaterialRequestItemId",
|
||||
"Value": "Talep"
|
||||
},
|
||||
{
|
||||
"Id": "200f7584-3208-5f8e-84a8-39208e09a680",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderQuote",
|
||||
"Value": "Supplier Quote"
|
||||
},
|
||||
{
|
||||
"Id": "94852784-af4e-5415-a9f6-2656d787c51d",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderQuote",
|
||||
"Value": "Tedarikçi Teklifi"
|
||||
},
|
||||
{
|
||||
"Id": "28b81d65-b19a-5ae1-a2bb-862ac8d6805d",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderQuote.Title",
|
||||
"Value": "Supplier Quote"
|
||||
},
|
||||
{
|
||||
"Id": "667bc350-7d02-56b5-905e-d995dc8f2e53",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderQuote.Title",
|
||||
"Value": "Tedarikçi Teklifi"
|
||||
},
|
||||
{
|
||||
"Id": "9078fafb-9fec-5f65-b6a3-db5653709174",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderQuote.Desc",
|
||||
"Value": "Supplier Quote — the supplier's answer to a request for quotation.\nWhere: Purchasing › Orders › Requests for Quotation › Supplier Quote tab (no menu of its own; edits the RFQ record itself).\nFields: supplier response (Waiting / Quoted / Not Quoted), quote date, quoted by (the user who entered the quote), quote validity date.\nUsage: when the response leaves Waiting, an empty quote date and quoted-by are filled automatically; quoted prices are entered on the Products tab."
|
||||
},
|
||||
{
|
||||
"Id": "a3a49de1-0e0f-51f7-93aa-3f71e6762da2",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderQuote.Desc",
|
||||
"Value": "Tedarikçi Teklifi — tedarikçinin teklif talebine verdiği yanıt.\nNerede: Satınalma › Siparişler › Teklif Talepleri › Tedarikçi Teklifi sekmesi (kendi menüsü yoktur; teklif kaydının kendisini düzenler).\nAlanlar: tedarikçi yanıtı (Bekleniyor / Teklif Verildi / Teklif Verilmedi), teklif tarihi, teklifi veren (teklifi sisteme işleyen kullanıcı), teklif geçerlilik tarihi.\nKullanım: yanıt Bekleniyor dışına alınınca boş teklif tarihi ve teklifi veren otomatik dolar; teklif edilen fiyatlar Ürünler sekmesine girilir."
|
||||
},
|
||||
{
|
||||
"Id": "19187136-bd1a-5b49-bc74-ed48b06ebf05",
|
||||
"CultureName": "en",
|
||||
|
|
@ -94406,20 +94364,6 @@
|
|||
"Key": "App.Listform.ListformField.QuoteDate",
|
||||
"Value": "Teklif Tarihi"
|
||||
},
|
||||
{
|
||||
"Id": "7818d8a6-d72b-535e-8337-42a275489755",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.QuotedByUserId",
|
||||
"Value": "Quoted By"
|
||||
},
|
||||
{
|
||||
"Id": "1d2d2c53-037e-5a49-ab44-7d3d2f0bb533",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.QuotedByUserId",
|
||||
"Value": "Teklifi Veren"
|
||||
},
|
||||
{
|
||||
"Id": "932757f4-c76c-58b4-85b5-e6c31798fbb6",
|
||||
"CultureName": "en",
|
||||
|
|
@ -94453,14 +94397,14 @@
|
|||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderOther.Desc",
|
||||
"Value": "Other Information — buyer, source, project and commercial terms of an RFQ or purchase order.\nWhere: Purchasing › Orders › Requests for Quotation and Purchase Orders › Other Information tab (no menu of its own; edits the document record itself).\nFields: buyer, source (material request numbers of the lines, written automatically, read-only), project, delivery term (Incoterm) and Incoterm location, payment term.\nDefaults: buyer, delivery term and payment term come from the supplier's Purchasing tab on the contact card."
|
||||
"Value": "Other Information — buyer, project and commercial terms of a purchase order.\nWhere: Purchasing › Orders › Purchase Orders › Other Information tab (no menu of its own; edits the order record itself).\nFields: buyer, payment term, project, delivery term (Incoterm) and its location.\nDefaults: buyer, payment and delivery terms come from the supplier's Purchasing tab on the contact card, or from the RFQ the order was converted from."
|
||||
},
|
||||
{
|
||||
"Id": "6cd4423d-a27f-5296-a05e-836db7e2a216",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderOther.Desc",
|
||||
"Value": "Diğer Bilgiler — teklif talebinin ya da satınalma siparişinin alıcı, kaynak, proje ve ticari koşulları.\nNerede: Satınalma › Siparişler › Teklif Talepleri ve Satınalma Siparişleri › Diğer Bilgiler sekmesi (kendi menüsü yoktur; belge kaydının kendisini düzenler).\nAlanlar: alıcı, kaynak (kalemlerin malzeme talebi numaraları, otomatik yazılır, salt okunur), proje, teslimat koşulu (Incoterm) ve Incoterm konumu, ödeme koşulu.\nVarsayılanlar: alıcı, teslimat ve ödeme koşulu tedarikçinin kontak kartındaki Satınalma sekmesinden gelir."
|
||||
"Value": "Diğer Bilgiler — satınalma siparişinin alıcı, proje ve ticari koşulları.\nNerede: Satınalma › Siparişler › Satınalma Siparişleri › Diğer Bilgiler sekmesi (kendi menüsü yoktur; sipariş kaydının kendisini düzenler).\nAlanlar: alıcı, ödeme koşulu, proje, teslimat koşulu (Incoterm) ve konumu.\nVarsayılanlar: alıcı, ödeme ve teslimat koşulu tedarikçinin kontak kartındaki Satınalma sekmesinden ya da siparişin dönüştürüldüğü teklif talebinden gelir."
|
||||
},
|
||||
{
|
||||
"Id": "7c052681-0033-5631-9a88-b3b90efc9866",
|
||||
|
|
@ -94509,42 +94453,42 @@
|
|||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderAlternative",
|
||||
"Value": "Alternative Quotes"
|
||||
"Value": "Source Quotes"
|
||||
},
|
||||
{
|
||||
"Id": "c9de6f14-e2a0-5e1c-801b-8b6887e5907a",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderAlternative",
|
||||
"Value": "Teklifler"
|
||||
"Value": "Kaynak Teklifler"
|
||||
},
|
||||
{
|
||||
"Id": "4942c90a-61d9-571f-81b1-162eb60974b1",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderAlternative.Title",
|
||||
"Value": "Alternative Quotes"
|
||||
"Value": "Source Quotes"
|
||||
},
|
||||
{
|
||||
"Id": "a75a7ad0-65ce-5b7d-9484-f06436e60b64",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderAlternative.Title",
|
||||
"Value": "Teklifler"
|
||||
"Value": "Kaynak Teklifler"
|
||||
},
|
||||
{
|
||||
"Id": "89ee160d-b1a1-5383-aa0a-3a5f8e542800",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderAlternative.Desc",
|
||||
"Value": "Alternative Quotes — other RFQs and purchase orders that carry lines of the same material requests as the open document.\nWhere: Purchasing › Orders › Requests for Quotation and Purchase Orders › Quotes tab (no menu of its own, read-only).\nFields: reference, supplier, supplier response, order deadline, expected arrival, total, currency, status.\nUsage: compare the quotes collected from different suppliers for the same request before confirming one of them."
|
||||
"Value": "Source Quotes — the requests for quotation of the tender the purchase order was converted from.\nWhere: Purchasing › Orders › Purchase Orders › Quotes tab (no menu of its own, read-only; empty for orders written without an RFQ).\nFields: RFQ no, supplier, status, supplier response, order deadline, expected arrival, untaxed amount, total, currency.\nUsage: see which suppliers were asked and which documents were converted or cancelled in the tender."
|
||||
},
|
||||
{
|
||||
"Id": "d938150e-9ec8-58be-a35f-bba058283961",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderAlternative.Desc",
|
||||
"Value": "Teklifler — açık belgeyle aynı malzeme talebinin kalemlerini taşıyan diğer teklif talepleri ve siparişler.\nNerede: Satınalma › Siparişler › Teklif Talepleri ve Satınalma Siparişleri › Teklifler sekmesi (kendi menüsü yoktur, salt okunur).\nAlanlar: referans, tedarikçi, tedarikçi yanıtı, sipariş zaman sınırı, beklenen geliş, toplam, para birimi, durum.\nKullanım: aynı talep için farklı tedarikçilerden toplanan teklifler, birini onaylamadan önce burada karşılaştırılır."
|
||||
"Value": "Kaynak Teklifler — satınalma siparişinin dönüştürüldüğü ihalenin teklif talepleri.\nNerede: Satınalma › Siparişler › Satınalma Siparişleri › Teklifler sekmesi (kendi menüsü yoktur, salt okunur; teklifsiz yazılan siparişte boştur).\nAlanlar: teklif talep no, tedarikçi, durum, tedarikçi yanıtı, sipariş zaman sınırı, beklenen geliş, vergi hariç tutar, toplam, para birimi.\nKullanım: ihalede hangi tedarikçilere sorulduğu, hangi belgenin siparişe dönüştüğü ve hangilerinin iptal edildiği görülür."
|
||||
},
|
||||
{
|
||||
"Id": "9b664716-c6b3-5b08-92df-173521e1ee92",
|
||||
|
|
@ -94602,20 +94546,6 @@
|
|||
"Key": "App.Prc.OrderStatus.Cancelled",
|
||||
"Value": "İptal Edildi"
|
||||
},
|
||||
{
|
||||
"Id": "3267fdd2-5b1b-5cc6-950a-732a3f7175c5",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.BaseOrderId",
|
||||
"Value": "Base Document"
|
||||
},
|
||||
{
|
||||
"Id": "db0ca289-8685-5d72-b89c-f194ad3d0571",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.BaseOrderId",
|
||||
"Value": "Ana Belge"
|
||||
},
|
||||
{
|
||||
"Id": "b399fe9f-85ff-5a82-91ec-43d9b490c0c3",
|
||||
"CultureName": "en",
|
||||
|
|
@ -94691,14 +94621,14 @@
|
|||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.Desc",
|
||||
"Value": "Requests for Quotation — every purchasing document in all states: RFQ, RFQ Sent, Purchase Order and Cancelled.\nWhere: Purchasing › Orders › Requests for Quotation; tabs Products, Supplier Quote, Other Information and Quotes.\nFields: reference (automatic, P00001), supplier, supplier reference, agreement, currency, order deadline, expected arrival, ask confirmation, deliver to (operation type), material request to import, action, untaxed / tax / total (calculated).\nAutomation: choosing a supplier fills currency, buyer and terms from the contact card; choosing an agreement fills an empty RFQ with its remaining lines; selecting an approved material request and saving copies its waiting purchase lines; the Action field (Send by e-mail / Confirm Order / Cancel / Set to Draft) runs on save — sending queues an e-mail to the supplier and moves the RFQ to RFQ Sent, confirming turns it into a purchase order."
|
||||
"Value": "Requests for Quotation — one purchasing document per supplier; documents opened for the same need form a tender and are compared before ordering.\nWhere: Purchasing › Orders › Requests for Quotation; tabs Products, Request Lines, Supplier Quote, Other Information, Quotes (other documents of the tender) and Price Comparison.\nStatuses: RFQ (draft) › RFQ Sent (e-mail queued to the supplier) › Purchase Order (converted) / Cancelled.\nFields: RFQ no (automatic, RFQ00001), supplier, supplier reference, agreement, currency, order deadline, expected arrival, ask confirmation, deliver to, terms; the list also shows tender, source (material request numbers of the lines), buyer and untaxed / tax / total (calculated from the lines).\nToolbar (select an RFQ): Import from Requests opens the approved request lines (several requests at once) to tick and save; Create Alternative adds suppliers to the tender (each gets a copy of the document with prices from its price list) and has a price entry table for all suppliers. The same work can be done in the Request Lines, Quotes and Price Comparison tabs. Choosing an agreement fills an empty RFQ with its remaining lines.\nStatus buttons (toolbar, confirmed before running): Send by E-mail, Send Whole Tender (all draft documents of the tender), Convert to Purchase Order (line by line: the Selected line, otherwise the Recommended line of the Price Comparison wins; one purchase order per winning supplier, documents that win nothing are cancelled), Cancel, Set to Draft (a cancelled RFQ). An RFQ converted or cancelled cannot be edited."
|
||||
},
|
||||
{
|
||||
"Id": "fb52ef21-5df4-55f3-98c3-3eeb9cc399e4",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.Desc",
|
||||
"Value": "Teklif Talepleri — her durumdaki satınalma belgeleri: Teklif Talebi, Teklif Talebi Gönderildi, Satınalma Siparişi ve İptal Edildi.\nNerede: Satınalma › Siparişler › Teklif Talepleri; sekmeler Ürünler, Tedarikçi Teklifi, Diğer Bilgiler ve Teklifler.\nAlanlar: referans (otomatik, P00001), tedarikçi, tedarikçi referansı, sözleşme, para birimi, sipariş zaman sınırı, beklenen geliş, onay isteyin, teslim alacak (operasyon türü), aktarılacak malzeme talebi, işlem, vergi hariç / KDV / toplam (hesaplanır).\nOtomasyon: tedarikçi seçilince para birimi, alıcı ve koşullar kontak kartından dolar; sözleşme seçilince boş teklif kalan sözleşme kalemleriyle dolar; onaylı bir malzeme talebi seçilip kaydedilince bekleyen satınalma kalemleri kopyalanır; İşlem alanı (E-posta ile Gönder / Siparişi Onayla / İptal / Taslak olarak ayarla) kayıtta çalışır — gönderim tedarikçiye e-posta kuyruğa alır ve teklifi Gönderildi yapar, onay teklifi satınalma siparişine çevirir."
|
||||
"Value": "Teklif Talepleri — her tedarikçi için ayrı satınalma belgesi; aynı ihtiyaç için açılan belgeler bir ihale oluşturur ve siparişten önce kıyaslanır.\nNerede: Satınalma › Siparişler › Teklif Talepleri; sekmeler Ürünler, Talep Kalemleri, Tedarikçi Teklifi, Diğer Bilgiler, Teklifler (ihalenin diğer belgeleri) ve Fiyat Karşılaştırması.\nDurumlar: Teklif Talebi (taslak) › Teklif Talebi Gönderildi (tedarikçiye e-posta kuyruğa alındı) › Satınalma Siparişi (dönüştürüldü) / İptal Edildi.\nAlanlar: teklif talep no (otomatik, RFQ00001), tedarikçi, tedarikçi referansı, sözleşme, para birimi, sipariş zaman sınırı, beklenen geliş, onay isteyin, teslim alacak, şartlar; listede ayrıca ihale, kaynak (kalemlerin malzeme talebi numaraları), alıcı ve vergi hariç / KDV / toplam (kalemlerden hesaplanır) görünür.\nAraç çubuğu (bir teklif seçilir): Talepten Aktar onaylı talep kalemlerini (birden fazla talep birlikte) işaretleyip kaydetmek için açar; Alternatif Oluştur ihaleye tedarikçi ekler (her biri belgenin kopyasını tedarikçinin fiyat listesiyle alır) ve bütün tedarikçiler için fiyat giriş tablosu sunar. Aynı işler Talep Kalemleri, Teklifler ve Fiyat Karşılaştırması sekmelerinden de yapılır. Sözleşme seçilince boş teklif kalan sözleşme kalemleriyle dolar.\nDurum butonları (araç çubuğu, çalışmadan önce onay ister): E-posta ile Gönder, İhaleyi Gönder (ihalenin bütün taslak belgeleri), Siparişe Dönüştür (kalem bazında: Fiyat Karşılaştırması'nda Seçili satır, yoksa Önerilen satır kazanır; kazanan her tedarikçiye bir satınalma siparişi açılır, hiç kalem kazanamayan belge iptal olur), İptal, Taslak olarak ayarla (iptal edilmiş teklif). Siparişe dönüşmüş ya da iptal edilmiş teklif düzenlenemez."
|
||||
},
|
||||
{
|
||||
"Id": "1bf349e4-0b50-53e2-9d5b-13da196cc214",
|
||||
|
|
@ -94812,34 +94742,6 @@
|
|||
"Key": "App.Prc.PurchaseOrder.Quotes",
|
||||
"Value": "Teklifler"
|
||||
},
|
||||
{
|
||||
"Id": "fbb8753c-8738-5520-953c-1bd660e4fc80",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrder.Widget.LateRfq",
|
||||
"Value": "Late RFQ"
|
||||
},
|
||||
{
|
||||
"Id": "f03c1c4e-2174-5b47-b6de-197bfe960999",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrder.Widget.LateRfq",
|
||||
"Value": "Geç RFQ"
|
||||
},
|
||||
{
|
||||
"Id": "29a104cb-314d-5f8b-a7a9-d4801a0928a9",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrder.Widget.NotAcknowledged",
|
||||
"Value": "Not Acknowledged"
|
||||
},
|
||||
{
|
||||
"Id": "251b169e-0f10-59aa-ba61-accb9753e1ff",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrder.Widget.NotAcknowledged",
|
||||
"Value": "Kabul Edilmedi"
|
||||
},
|
||||
{
|
||||
"Id": "d0669f99-2388-5884-8e2f-27dd33603b1c",
|
||||
"CultureName": "en",
|
||||
|
|
@ -94852,35 +94754,7 @@
|
|||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrder.Widget.LateReceipt",
|
||||
"Value": "Geç Makbuz"
|
||||
},
|
||||
{
|
||||
"Id": "bb93cf35-e065-57c3-94a5-d4c1660660d2",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrder.Widget.Otd",
|
||||
"Value": "OTD %"
|
||||
},
|
||||
{
|
||||
"Id": "44d5c9e7-5a0d-5701-a5b5-c0a12ac07124",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrder.Widget.Otd",
|
||||
"Value": "OTD %"
|
||||
},
|
||||
{
|
||||
"Id": "3b373f46-3234-582c-b931-52c4c0453a9c",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrder.Widget.Mine",
|
||||
"Value": "My"
|
||||
},
|
||||
{
|
||||
"Id": "7c121494-f7cf-501a-9904-e03de6464446",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrder.Widget.Mine",
|
||||
"Value": "Benim"
|
||||
"Value": "Geciken Teslim"
|
||||
},
|
||||
{
|
||||
"Id": "c8bea494-718f-5fad-805f-5c52c9c30b5b",
|
||||
|
|
@ -94985,14 +94859,14 @@
|
|||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrder.Desc",
|
||||
"Value": "Purchase Orders — RFQs confirmed as purchase orders.\nWhere: Purchasing › Orders › Purchase Orders; new orders are created in Requests for Quotation with the Confirm Order action. Tabs: Products, Other Information, Quotes.\nFields: reference, confirmation date, supplier, supplier reference, agreement, currency, expected arrival, arrival (entered when the goods arrive), deliver to, source material requests, untaxed / tax / total (calculated).\nActions (Action field, runs on save): Send by E-mail queues the order to the supplier's contact e-mail; Cancel cancels the order. More waiting purchase lines can be imported from an approved material request. Late Receipt counts orders past expected arrival without an arrival date."
|
||||
"Value": "Purchase Orders — orders given to suppliers, either converted from a tender of requests for quotation or written directly without collecting quotes.\nWhere: Purchasing › Orders › Purchase Orders; tabs Products, Request Lines (draft orders), Other Information and Quotes (the RFQs of the source tender).\nStatuses: Draft › Confirmed / Cancelled; orders converted from an RFQ open confirmed.\nFields: order no (automatic, P00001), supplier, supplier reference, agreement, currency, confirmation date, expected arrival, arrival (entered when the goods arrive), deliver to, terms; the list also shows untaxed / tax / total (calculated from the lines); Source shows the RFQ no when converted from a quote, otherwise the material request numbers.\nToolbar (select an order): Import from Requests (draft orders), and the status buttons Confirm Order, Send by E-mail (queues the order with prices to the supplier's contact e-mail), Cancel, Set to Draft (a cancelled order); status buttons ask for confirmation. Only a draft order written without an RFQ can be deleted; a cancelled order cannot be edited."
|
||||
},
|
||||
{
|
||||
"Id": "478b1fe5-8780-55e4-a308-2fc0925fbfba",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrder.Desc",
|
||||
"Value": "Satınalma Siparişleri — siparişe çevrilmiş teklif talepleri.\nNerede: Satınalma › Siparişler › Satınalma Siparişleri; yeni sipariş Teklif Talepleri'nde Siparişi Onayla işlemiyle oluşur. Sekmeler: Ürünler, Diğer Bilgiler, Teklifler.\nAlanlar: referans, onaylama tarihi, tedarikçi, tedarikçi referansı, sözleşme, para birimi, beklenen geliş, varış (mal gelince girilir), teslim alacak, kaynak malzeme talepleri, vergi hariç / KDV / toplam (hesaplanır).\nİşlemler (İşlem alanı, kayıtta çalışır): E-posta ile Gönder siparişi tedarikçinin kontak e-postasına kuyruğa alır; İptal siparişi iptal eder. Onaylı bir malzeme talebinden bekleyen satınalma kalemleri ayrıca aktarılabilir. Geç Makbuz, beklenen gelişi geçmiş ve varışı girilmemiş siparişleri sayar."
|
||||
"Value": "Satınalma Siparişleri — tedarikçilere verilen siparişler; teklif talebi ihalesinden dönüştürülür ya da teklif toplamadan doğrudan yazılır.\nNerede: Satınalma › Siparişler › Satınalma Siparişleri; sekmeler Ürünler, Talep Kalemleri (taslak siparişte), Diğer Bilgiler ve Teklifler (kaynak ihalenin teklif talepleri).\nDurumlar: Taslak › Onaylandı / İptal; teklif talebinden dönüştürülen sipariş onaylı açılır.\nAlanlar: sipariş no (otomatik, P00001), tedarikçi, tedarikçi referansı, sözleşme, para birimi, onaylama tarihi, beklenen geliş, varış (mal gelince girilir), teslim alacak, şartlar; listede ayrıca vergi hariç / KDV / toplam (kalemlerden hesaplanır) görünür; Kaynak teklif talebinden gelen siparişte teklif talep no, doğrudan yazılanda malzeme talebi numaralarıdır.\nAraç çubuğu (bir sipariş seçilir): Talepten Aktar (taslak siparişte) ve durum butonları Siparişi Onayla, E-posta ile Gönder (sipariş fiyatlarıyla tedarikçinin kontak e-postasına kuyruğa alınır), İptal, Taslak olarak ayarla (iptal edilmiş sipariş); durum butonları onay ister. Yalnız teklifsiz yazılmış taslak sipariş silinebilir; iptal edilmiş sipariş düzenlenemez."
|
||||
},
|
||||
{
|
||||
"Id": "20bc4aa0-2cd4-5f36-90fc-839ccc16bedc",
|
||||
|
|
@ -95035,6 +94909,608 @@
|
|||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.ArrivalDate",
|
||||
"Value": "Varış"
|
||||
},
|
||||
{
|
||||
"Id": "62b2e1f0-ab1e-5598-930e-185ab2ea7c9d",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqLine",
|
||||
"Value": "RFQ Lines"
|
||||
},
|
||||
{
|
||||
"Id": "eda648f3-9907-53ec-9660-96fb8c7e0603",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqLine",
|
||||
"Value": "Teklif Kalemleri"
|
||||
},
|
||||
{
|
||||
"Id": "9f2610f4-c31d-514b-b623-494161c83a5d",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqLine.Title",
|
||||
"Value": "RFQ Lines"
|
||||
},
|
||||
{
|
||||
"Id": "7948da66-c5d3-5ad1-a1f9-526b506af4cf",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqLine.Title",
|
||||
"Value": "Teklif Kalemleri"
|
||||
},
|
||||
{
|
||||
"Id": "b6ec0bb2-6059-5367-a3e7-ac67ed7c89b5",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqLine.Desc",
|
||||
"Value": "RFQ Lines — the products of a request for quotation and the supplier's price and delivery date for each.\nWhere: Purchasing › Orders › Requests for Quotation › Products tab (no menu of its own).\nFields: product, description, quantity, unit, unit price, tax rate, amount (quantity × unit price, calculated), delivery date (requested date from the material request, replaced by the supplier's date), material request line (read-only).\nRules: lines cannot be changed on an RFQ converted to a purchase order or cancelled; after every change the RFQ totals are recalculated. Lines added after alternatives were created stay on this document only."
|
||||
},
|
||||
{
|
||||
"Id": "a94f677b-7bc1-56b2-9271-7998f6d45f23",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqLine.Desc",
|
||||
"Value": "Teklif Kalemleri — teklif talebinin ürünleri ve tedarikçinin her biri için verdiği fiyat ile termin.\nNerede: Satınalma › Siparişler › Teklif Talepleri › Ürünler sekmesi (kendi menüsü yoktur).\nAlanlar: ürün, açıklama, miktar, birim, birim fiyat, vergi oranı, tutar (miktar × birim fiyat, hesaplanır), teslim tarihi (malzeme talebindeki istenen termin; tedarikçinin terminiyle değiştirilir), talep kalemi (salt okunur).\nKurallar: siparişe dönüştürülmüş ya da iptal edilmiş teklifin kalemi değiştirilemez; her değişiklikte teklif toplamları yeniden hesaplanır. Alternatifler açıldıktan sonra eklenen kalem yalnız bu belgede kalır."
|
||||
},
|
||||
{
|
||||
"Id": "d9751641-bb8e-5e79-bb6d-65754d307617",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.PurchaseRfqId",
|
||||
"Value": "RFQ"
|
||||
},
|
||||
{
|
||||
"Id": "d721294c-3f74-5351-9c7e-e75005859abc",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.PurchaseRfqId",
|
||||
"Value": "Teklif Talebi"
|
||||
},
|
||||
{
|
||||
"Id": "e90418f1-9dce-587c-80a1-aed32440d057",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqImportItem",
|
||||
"Value": "RFQ Request Lines"
|
||||
},
|
||||
{
|
||||
"Id": "6b0e4bad-152a-5cb2-81e4-2b2cbbe1e020",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqImportItem",
|
||||
"Value": "Teklif Talep Kalemleri"
|
||||
},
|
||||
{
|
||||
"Id": "9b1be119-7cde-5e9a-aa18-dc16284a1b58",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqImportItem.Title",
|
||||
"Value": "RFQ Request Lines"
|
||||
},
|
||||
{
|
||||
"Id": "a830862e-42cd-5a87-a57d-bfe8649de485",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqImportItem.Title",
|
||||
"Value": "Teklif Talep Kalemleri"
|
||||
},
|
||||
{
|
||||
"Id": "9833ca85-9823-5e08-9943-1b44047ae927",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqImportItem.Desc",
|
||||
"Value": "RFQ Request Lines — the lines of approved material requests that can still be quoted, listed for the open request for quotation.\nWhere: Purchasing › Orders › Requests for Quotation › Request Lines tab (no menu of its own); grouped by request.\nFields: request no, requester, product, quantity, unit, requested date, reason, transfer.\nUsage: tick Transfer on as many lines as needed (several requests at once) and press Save; the lines are copied to the RFQ with the agreement or supplier price and the requested date, and disappear from this list. Only an RFQ in RFQ or RFQ Sent status takes lines; a line already on another active RFQ or order is not listed."
|
||||
},
|
||||
{
|
||||
"Id": "377297ab-417d-5583-89eb-f6c7ee0a0f66",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqImportItem.Desc",
|
||||
"Value": "Teklif Talep Kalemleri — onaylı malzeme taleplerinin henüz teklif istenmemiş kalemleri, açık teklif talebi için listelenir.\nNerede: Satınalma › Siparişler › Teklif Talepleri › Talep Kalemleri sekmesi (kendi menüsü yoktur); talebe göre gruplanır.\nAlanlar: talep no, talep eden, ürün, miktar, birim, istenen tarih, neden, aktar.\nKullanım: istenen kadar satırda (birden fazla talep birlikte) Aktar işaretlenip Kaydet'e basılır; kalemler sözleşme ya da tedarikçi fiyatı ve istenen termin ile teklife kopyalanır ve bu listeden düşer. Yalnız Teklif Talebi ya da Gönderildi durumundaki teklife kalem aktarılır; başka bir açık teklifte ya da siparişte olan kalem listelenmez."
|
||||
},
|
||||
{
|
||||
"Id": "d9cc2ab9-013b-570a-8d78-7af6e62ec4c3",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.BaseId",
|
||||
"Value": "Base Document"
|
||||
},
|
||||
{
|
||||
"Id": "b5e0cd61-95ff-5fae-b7a8-f99f728e02fc",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.BaseId",
|
||||
"Value": "Ana Belge"
|
||||
},
|
||||
{
|
||||
"Id": "45dc952c-b38b-559e-92ae-1edd304cb773",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.Transfer",
|
||||
"Value": "Transfer"
|
||||
},
|
||||
{
|
||||
"Id": "b41a0c77-801b-5247-b35a-7880611e45e1",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.Transfer",
|
||||
"Value": "Aktar"
|
||||
},
|
||||
{
|
||||
"Id": "e55b855c-35b4-5a79-be40-684965c8c3ca",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqQuote",
|
||||
"Value": "Supplier Quote"
|
||||
},
|
||||
{
|
||||
"Id": "7b51de5d-185e-5a52-b9fb-5a23430a0ffe",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqQuote",
|
||||
"Value": "Tedarikçi Teklifi"
|
||||
},
|
||||
{
|
||||
"Id": "167f7073-40c0-5226-bc64-0ab8e63030a2",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqQuote.Title",
|
||||
"Value": "Supplier Quote"
|
||||
},
|
||||
{
|
||||
"Id": "69fda088-14b6-5513-acbe-9548d2ad722b",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqQuote.Title",
|
||||
"Value": "Tedarikçi Teklifi"
|
||||
},
|
||||
{
|
||||
"Id": "28e710e3-f1f1-5ab3-b290-f96bab3f4b88",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqQuote.Desc",
|
||||
"Value": "Supplier Quote — the supplier's answer to a request for quotation.\nWhere: Purchasing › Orders › Requests for Quotation › Supplier Quote tab (no menu of its own; edits the RFQ record itself).\nFields: supplier response (Waiting / Quoted / Not Quoted), quote date, quote validity date.\nUsage: when the response leaves Waiting an empty quote date is filled; quoted prices and delivery dates are entered on the Products tab or in the Price Comparison tab. An RFQ answered Not Quoted is left out of the comparison."
|
||||
},
|
||||
{
|
||||
"Id": "b5a23ccd-b75c-5e76-b2cb-a366658e526f",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqQuote.Desc",
|
||||
"Value": "Tedarikçi Teklifi — tedarikçinin teklif talebine verdiği yanıt.\nNerede: Satınalma › Siparişler › Teklif Talepleri › Tedarikçi Teklifi sekmesi (kendi menüsü yoktur; teklif kaydının kendisini düzenler).\nAlanlar: tedarikçi yanıtı (Bekleniyor / Teklif Verildi / Teklif Verilmedi), teklif tarihi, teklif geçerlilik tarihi.\nKullanım: yanıt Bekleniyor dışına alınınca boş teklif tarihi dolar; teklif edilen fiyat ve terminler Ürünler ya da Fiyat Karşılaştırması sekmesine girilir. Teklif Verilmedi yanıtlı belge kıyasa girmez."
|
||||
},
|
||||
{
|
||||
"Id": "582fbae3-23f7-588c-9bb6-35bb219baf39",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqOther",
|
||||
"Value": "RFQ Other Information"
|
||||
},
|
||||
{
|
||||
"Id": "ecddc1d5-567c-57a9-a86f-2323d60a5677",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqOther",
|
||||
"Value": "Teklif Diğer Bilgiler"
|
||||
},
|
||||
{
|
||||
"Id": "6fb7d374-1f21-545e-a756-71c7edf12b61",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqOther.Title",
|
||||
"Value": "RFQ Other Information"
|
||||
},
|
||||
{
|
||||
"Id": "89629f51-38c9-55b6-9f98-f66a00010772",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqOther.Title",
|
||||
"Value": "Teklif Diğer Bilgiler"
|
||||
},
|
||||
{
|
||||
"Id": "71347518-d862-5a33-b6f9-ff05885cdc82",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqOther.Desc",
|
||||
"Value": "RFQ Other Information — buyer, project, commercial terms and the comparison weights of a request for quotation.\nWhere: Purchasing › Orders › Requests for Quotation › Other Information tab (no menu of its own; edits the RFQ record itself).\nFields: buyer, payment term, project, delivery term (Incoterm) and its location, price weight and delivery weight (%).\nRules: the two weights must add up to 100 (default 70 / 30) and are shared by the whole tender — a change is written to every document of the tender; buyer, payment and delivery terms default from the supplier's Purchasing tab."
|
||||
},
|
||||
{
|
||||
"Id": "736d6fe4-32b1-56d8-82c3-a42f69b7ff25",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqOther.Desc",
|
||||
"Value": "Teklif Diğer Bilgiler — teklif talebinin alıcı, proje, ticari koşulları ve kıyas ağırlıkları.\nNerede: Satınalma › Siparişler › Teklif Talepleri › Diğer Bilgiler sekmesi (kendi menüsü yoktur; teklif kaydının kendisini düzenler).\nAlanlar: alıcı, ödeme koşulu, proje, teslimat koşulu (Incoterm) ve konumu, fiyat ağırlığı ve termin ağırlığı (%).\nKurallar: iki ağırlığın toplamı 100 olmalıdır (varsayılan 70 / 30) ve ihale genelinde tektir — değişiklik ihalenin bütün belgelerine yazılır; alıcı, ödeme ve teslimat koşulu tedarikçinin Satınalma sekmesinden gelir."
|
||||
},
|
||||
{
|
||||
"Id": "81d0a0d1-4c52-5fc5-8138-b49ef0b81a45",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.PriceWeight",
|
||||
"Value": "Price Weight (%)"
|
||||
},
|
||||
{
|
||||
"Id": "e5dcde98-bd97-557c-86e9-ea86936c0c64",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.PriceWeight",
|
||||
"Value": "Fiyat Ağırlığı (%)"
|
||||
},
|
||||
{
|
||||
"Id": "ac75dc88-0d2c-54ee-9840-2b0c9f85a279",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.DeliveryWeight",
|
||||
"Value": "Delivery Weight (%)"
|
||||
},
|
||||
{
|
||||
"Id": "1d9bcf08-7ab2-5f8c-95ce-bc8a867a67a6",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.DeliveryWeight",
|
||||
"Value": "Termin Ağırlığı (%)"
|
||||
},
|
||||
{
|
||||
"Id": "f7272f00-c353-5233-9837-2350412be83f",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqAlternative",
|
||||
"Value": "Tender Quotes"
|
||||
},
|
||||
{
|
||||
"Id": "a35ea338-ef22-5d59-a931-ea1ac785be01",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqAlternative",
|
||||
"Value": "İhale Teklifleri"
|
||||
},
|
||||
{
|
||||
"Id": "f982a0e8-fd9d-5877-839b-dda769d30e5b",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqAlternative.Title",
|
||||
"Value": "Tender Quotes"
|
||||
},
|
||||
{
|
||||
"Id": "998f3258-8225-5bc7-b8d7-3276a88b7ea7",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqAlternative.Title",
|
||||
"Value": "İhale Teklifleri"
|
||||
},
|
||||
{
|
||||
"Id": "d03215ef-640e-5720-b090-37359c8c8b94",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqAlternative.Desc",
|
||||
"Value": "Tender Quotes — the other requests for quotation of the same tender; alternatives are created here.\nWhere: Purchasing › Orders › Requests for Quotation › Quotes tab (no menu of its own).\nFields: RFQ no, supplier, status, supplier response, order deadline, expected arrival, untaxed amount, total, currency.\nUsage: Add + supplier creates an alternative RFQ in the same tender with a copy of the current lines (price from the supplier's price list, currency and terms from the contact card); a supplier can be in a tender once. Prices of all alternatives are entered together in the Price Comparison tab."
|
||||
},
|
||||
{
|
||||
"Id": "18b7fd92-8a1b-56bb-9b1f-587605c955cd",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqAlternative.Desc",
|
||||
"Value": "İhale Teklifleri — aynı ihalenin diğer teklif talepleri; alternatifler burada oluşturulur.\nNerede: Satınalma › Siparişler › Teklif Talepleri › Teklifler sekmesi (kendi menüsü yoktur).\nAlanlar: teklif talep no, tedarikçi, durum, tedarikçi yanıtı, sipariş zaman sınırı, beklenen geliş, vergi hariç tutar, toplam, para birimi.\nKullanım: Ekle + tedarikçi seçimi aynı ihalede, o anki kalemlerin kopyasıyla alternatif teklif talebi açar (fiyat tedarikçinin fiyat listesinden, para birimi ve koşullar kontak kartından); bir tedarikçi ihalede bir kez bulunur. Bütün alternatiflerin fiyatları Fiyat Karşılaştırması sekmesinde birlikte girilir."
|
||||
},
|
||||
{
|
||||
"Id": "21d2f612-dde9-517c-8441-f554f131689a",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.RfqNo",
|
||||
"Value": "RFQ No"
|
||||
},
|
||||
{
|
||||
"Id": "79c6c4e8-659a-5891-938d-c8feaa163d9d",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.RfqNo",
|
||||
"Value": "Teklif Talep No"
|
||||
},
|
||||
{
|
||||
"Id": "dd05e596-83bd-539d-9796-0839e93a574b",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqComparison",
|
||||
"Value": "Price Comparison"
|
||||
},
|
||||
{
|
||||
"Id": "a8f2cc02-6ba3-5547-9ccc-b4d031a3724e",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqComparison",
|
||||
"Value": "Fiyat Karşılaştırması"
|
||||
},
|
||||
{
|
||||
"Id": "d71d375a-00ae-5f42-82a6-29f8d96bfe52",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqComparison.Title",
|
||||
"Value": "Price Comparison"
|
||||
},
|
||||
{
|
||||
"Id": "7b7b6c36-463d-57ba-8fb2-840339bdec22",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqComparison.Title",
|
||||
"Value": "Fiyat Karşılaştırması"
|
||||
},
|
||||
{
|
||||
"Id": "7b6e120e-eaca-54cd-8f41-68e8e1f5e0f2",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqComparison.Desc",
|
||||
"Value": "Price Comparison — every line of the tender side by side for each supplier, scored by price and delivery time.\nWhere: Purchasing › Orders › Requests for Quotation › Price Comparison tab (no menu of its own); grouped by product.\nFields: product, RFQ no, supplier, status, quantity, unit, unit price, currency, price in TRY (currency rate), delivery date, lead time in days (from the tender start), score, recommended, selected.\nCalculation: score = price weight × lowest TRY price / TRY price + delivery weight × shortest lead time / lead time (weights from Other Information, default 70 / 30); the highest score is Recommended. Lines without price or delivery date, of a Not Quoted or cancelled RFQ are not scored.\nUsage: unit price, delivery date and Selected are typed directly in the grid for all suppliers and saved together with Save; ticking Selected overrides the recommendation for that product when the tender is converted to purchase orders."
|
||||
},
|
||||
{
|
||||
"Id": "016d1c7e-0b3a-5854-a45f-4a884805a1eb",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfqComparison.Desc",
|
||||
"Value": "Fiyat Karşılaştırması — ihalenin her kalemi tedarikçi bazında yan yana, fiyat ve termine göre puanlanmış.\nNerede: Satınalma › Siparişler › Teklif Talepleri › Fiyat Karşılaştırması sekmesi (kendi menüsü yoktur); ürüne göre gruplanır.\nAlanlar: ürün, teklif talep no, tedarikçi, durum, miktar, birim, birim fiyat, para birimi, TL fiyat (kurla), teslim tarihi, termin günü (ihalenin açılışından), puan, önerilen, seçili.\nHesap: puan = fiyat ağırlığı × en düşük TL fiyat / TL fiyat + termin ağırlığı × en kısa termin / termin (ağırlıklar Diğer Bilgiler'den, varsayılan 70 / 30); en yüksek puan Önerilen'dir. Fiyatı ya da terminsiz satır, Teklif Verilmedi ya da iptal edilmiş belgenin satırı puanlanmaz.\nKullanım: birim fiyat, teslim tarihi ve Seçili bütün tedarikçiler için doğrudan tabloda yazılır ve Kaydet ile birlikte kaydedilir; Seçili işaretlenen satır, ihale siparişe dönüştürülürken o ürün için öneriyi geçersiz kılar."
|
||||
},
|
||||
{
|
||||
"Id": "ddfdb3d9-1ed6-5bbd-a59d-12da60bfdce2",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.PriceTry",
|
||||
"Value": "Price (TRY)"
|
||||
},
|
||||
{
|
||||
"Id": "dca85550-c643-5f9d-b123-d0fa6a8fc0f4",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.PriceTry",
|
||||
"Value": "Fiyat (TL)"
|
||||
},
|
||||
{
|
||||
"Id": "a75b25b2-4111-50ed-aa45-82d79ffbae72",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.LeadDays",
|
||||
"Value": "Lead Time (Days)"
|
||||
},
|
||||
{
|
||||
"Id": "f6a4c1b0-a443-5b64-8aa4-559bcc1d6138",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.LeadDays",
|
||||
"Value": "Termin (Gün)"
|
||||
},
|
||||
{
|
||||
"Id": "c1d177c6-226a-5490-9bd7-9773ce279910",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.IsRecommended",
|
||||
"Value": "Recommended"
|
||||
},
|
||||
{
|
||||
"Id": "991264cb-61eb-578d-8503-7911b6b26e2c",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.IsRecommended",
|
||||
"Value": "Önerilen"
|
||||
},
|
||||
{
|
||||
"Id": "0be8a867-28a6-5601-a345-1b0a27866054",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.IsSelected",
|
||||
"Value": "Selected"
|
||||
},
|
||||
{
|
||||
"Id": "863556c3-9d58-55fb-b50e-32e67489c92e",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.IsSelected",
|
||||
"Value": "Seçili"
|
||||
},
|
||||
{
|
||||
"Id": "877d4291-3abd-5ac8-a4ba-5f24aacf5b36",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderImportItem",
|
||||
"Value": "Order Request Lines"
|
||||
},
|
||||
{
|
||||
"Id": "be684e5d-b6e0-5bd2-941e-86c28be49bc1",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderImportItem",
|
||||
"Value": "Sipariş Talep Kalemleri"
|
||||
},
|
||||
{
|
||||
"Id": "667c18cc-30a5-591b-b0a0-ed709121e1a2",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderImportItem.Title",
|
||||
"Value": "Order Request Lines"
|
||||
},
|
||||
{
|
||||
"Id": "18e378bd-d084-5444-a5e8-059ab2e55c8c",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderImportItem.Title",
|
||||
"Value": "Sipariş Talep Kalemleri"
|
||||
},
|
||||
{
|
||||
"Id": "3f458748-e79e-5e58-9197-6a1db3179fba",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderImportItem.Desc",
|
||||
"Value": "Order Request Lines — the lines of approved material requests that are not on any RFQ or order yet, listed for a draft purchase order written without quotes.\nWhere: Purchasing › Orders › Purchase Orders › Request Lines tab (no menu of its own); grouped by request; only a draft order takes lines.\nFields: request no, requester, product, quantity, unit, requested date, reason, transfer.\nUsage: tick Transfer on the lines to order (several requests at once) and press Save; the lines are copied with the agreement or supplier price and the requested date, and the order's Source shows the request numbers."
|
||||
},
|
||||
{
|
||||
"Id": "a6c01942-c13c-5ff4-9367-ac1ab75975f5",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrderImportItem.Desc",
|
||||
"Value": "Sipariş Talep Kalemleri — onaylı malzeme taleplerinin henüz hiçbir teklifte ya da siparişte olmayan kalemleri, teklifsiz yazılan taslak sipariş için listelenir.\nNerede: Satınalma › Siparişler › Satınalma Siparişleri › Talep Kalemleri sekmesi (kendi menüsü yoktur); talebe göre gruplanır; yalnız taslak sipariş kalem alır.\nAlanlar: talep no, talep eden, ürün, miktar, birim, istenen tarih, neden, aktar.\nKullanım: sipariş edilecek satırlarda (birden fazla talep birlikte) Aktar işaretlenip Kaydet'e basılır; kalemler sözleşme ya da tedarikçi fiyatı ve istenen termin ile kopyalanır, siparişin Kaynak'ında talep numaraları görünür."
|
||||
},
|
||||
{
|
||||
"Id": "c5599c91-6f69-5811-bf9e-659fd95ce8a9",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.Action.SendTender",
|
||||
"Value": "Send Whole Tender"
|
||||
},
|
||||
{
|
||||
"Id": "75e50faf-d537-55fa-aa89-aebdd7c94f86",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.Action.SendTender",
|
||||
"Value": "İhaleyi Gönder"
|
||||
},
|
||||
{
|
||||
"Id": "e37ee257-4bff-569d-93aa-807235718f48",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.Action.Award",
|
||||
"Value": "Convert to Purchase Order"
|
||||
},
|
||||
{
|
||||
"Id": "e329d74e-6ca9-58f7-9e41-c848307da8d3",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.Action.Award",
|
||||
"Value": "Siparişe Dönüştür"
|
||||
},
|
||||
{
|
||||
"Id": "853f6fd8-4f09-5643-86ab-002a0e793c9d",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.ImportRequests",
|
||||
"Value": "Import from Requests"
|
||||
},
|
||||
{
|
||||
"Id": "0653a1b5-2aa0-5ced-8a37-d6105c023edf",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.ImportRequests",
|
||||
"Value": "Talepten Aktar"
|
||||
},
|
||||
{
|
||||
"Id": "6ac7c8e8-b667-586a-9744-1109f6e185bf",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.ImportRequestsInfo",
|
||||
"Value": "Tick Transfer on the lines to bring in (several requests at once) and press Save in the table toolbar."
|
||||
},
|
||||
{
|
||||
"Id": "2bf8cbca-a022-53fa-9c86-61d478c6cba0",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.ImportRequestsInfo",
|
||||
"Value": "Aktarılacak satırlarda Aktar'ı işaretleyin (birden fazla talep birlikte) ve tablonun araç çubuğundaki Kaydet'e basın."
|
||||
},
|
||||
{
|
||||
"Id": "e6f0c745-a48c-520e-b3cd-d1bce35ba78d",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.CreateAlternative",
|
||||
"Value": "Create Alternative"
|
||||
},
|
||||
{
|
||||
"Id": "2f4ef246-21b8-57fe-9e37-5f601513a188",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.CreateAlternative",
|
||||
"Value": "Alternatif Oluştur"
|
||||
},
|
||||
{
|
||||
"Id": "461bfd03-19c2-510a-a228-c8c277004e39",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.AlternativeSuppliers",
|
||||
"Value": "Suppliers"
|
||||
},
|
||||
{
|
||||
"Id": "916e6daf-bfee-5da6-8720-a5f5dc51cc72",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.AlternativeSuppliers",
|
||||
"Value": "Tedarikçiler"
|
||||
},
|
||||
{
|
||||
"Id": "a367fc99-7842-5092-ae10-5e8130c67c4e",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.PriceEntry",
|
||||
"Value": "Price Entry"
|
||||
},
|
||||
{
|
||||
"Id": "9f98ce28-f22e-5086-9f12-30af2f1f668a",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.PriceEntry",
|
||||
"Value": "Fiyat Girişi"
|
||||
},
|
||||
{
|
||||
"Id": "01dc669c-64aa-5d4f-abf1-9ec922c6eb75",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrder.ConfirmAction",
|
||||
"Value": "Apply this action to the selected document?"
|
||||
},
|
||||
{
|
||||
"Id": "ef52de72-e2f8-54b9-b812-139f8b4e71ab",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseOrder.ConfirmAction",
|
||||
"Value": "Bu işlem seçili belgeye uygulansın mı?"
|
||||
},
|
||||
{
|
||||
"Id": "b07c57e5-8140-5406-b5c1-f7686b1a03d6",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.PriceComparison",
|
||||
"Value": "Price Comparison"
|
||||
},
|
||||
{
|
||||
"Id": "2f284ab1-e8b2-5f33-b657-25bb589bd63b",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.PriceComparison",
|
||||
"Value": "Fiyat Karşılaştırması"
|
||||
},
|
||||
{
|
||||
"Id": "fd80636e-9f05-5a48-84a8-09d837f3cbae",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.RequestItems",
|
||||
"Value": "Request Lines"
|
||||
},
|
||||
{
|
||||
"Id": "85d7d59b-32a9-568c-ac95-49cfe7b50554",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Prc.PurchaseRfq.RequestItems",
|
||||
"Value": "Talep Kalemleri"
|
||||
},
|
||||
{
|
||||
"Id": "88e499b0-3bd3-5cb3-a451-c20fcd75e97c",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.TenderGroupId",
|
||||
"Value": "Tender"
|
||||
},
|
||||
{
|
||||
"Id": "d5cecbfe-ab25-5945-97f0-ca820ffbba6a",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Listform.ListformField.TenderGroupId",
|
||||
"Value": "İhale"
|
||||
},
|
||||
{
|
||||
"Id": "1294743f-731b-5b07-a147-8b4d5b54d6aa",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.StaticLookup.Confirmed",
|
||||
"Value": "Confirmed"
|
||||
},
|
||||
{
|
||||
"Id": "fa47eeb0-c8b5-5a0f-9bf2-1e5389c1b7f3",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.StaticLookup.Confirmed",
|
||||
"Value": "Onaylandı"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,6 +153,26 @@
|
|||
"IsActive": true,
|
||||
"IsFixed": false,
|
||||
"IsCustomized": false
|
||||
},
|
||||
{
|
||||
"Id": "79e2e341-cbf3-5909-b828-0daf893e1b34",
|
||||
"NotificationTypeId": "8de88689-3dde-5ed9-b41f-a8bb287e7094",
|
||||
"RecipientType": "Custom",
|
||||
"RecipientId": null,
|
||||
"Channel": "Mail",
|
||||
"IsActive": true,
|
||||
"IsFixed": false,
|
||||
"IsCustomized": false
|
||||
},
|
||||
{
|
||||
"Id": "5371d2f1-0939-589d-b2d3-674b4dbf1ddf",
|
||||
"NotificationTypeId": "bbb44959-fb0b-56f8-9b63-693f6480b45d",
|
||||
"RecipientType": "Custom",
|
||||
"RecipientId": null,
|
||||
"Channel": "Mail",
|
||||
"IsActive": true,
|
||||
"IsFixed": false,
|
||||
"IsCustomized": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,21 +4,6 @@
|
|||
"GeneratedAt": "2026-09-18T06:12:57.546144Z",
|
||||
"Order": 1,
|
||||
"Rows": [
|
||||
{
|
||||
"Id": "095dcdb5-7c4a-5668-81bb-abc7b01b2158",
|
||||
"Name": "YeniSiparis",
|
||||
"Description": "Yeni bir sipariş oluşturulduğunda tetiklenir. Siparişi karşılayacak ekibin haberdar olması içindir; mesaj metni sipariş numarası ve müşteri adı gibi bilgileri taşır. Tetikleyici genellikle sipariş ekranının kayıt sonrası komutu ya da sipariş tablosunu yazan saklı yordamdır."
|
||||
},
|
||||
{
|
||||
"Id": "c58237f7-edd6-55a3-9bc9-aab82f63ca3e",
|
||||
"Name": "SiparisPasla",
|
||||
"Description": "Bir sipariş başka bir kullanıcıya ya da ekibe devredildiğinde tetiklenir. Devralının işi sahiplendiğini bilmesi içindir; mesajda kimin kime devrettiği ve sipariş bilgisi geçer."
|
||||
},
|
||||
{
|
||||
"Id": "78a4b82b-de80-5826-bf9b-e49a2436cd43",
|
||||
"Name": "YeniKullanici",
|
||||
"Description": "Sisteme yeni bir kullanıcı eklendiğinde tetiklenir. Yönetici ekibin yetki ve rol atamasını yapması için haberdar olmasını sağlar."
|
||||
},
|
||||
{
|
||||
"Id": "8eaa322e-76bb-592a-8200-666442c03e23",
|
||||
"Name": "DenemeSuresiBitiyor",
|
||||
|
|
@ -53,6 +38,16 @@
|
|||
"Id": "7ea2271f-e71c-5b63-8826-9df5e632eb4b",
|
||||
"Name": "IzinTalebiSonuclandi",
|
||||
"Description": "İzin talebi onaylandığında ya da reddedildiğinde talep sahibi çalışana gider. Alıcı talepten gelir; bu tipin Custom kuralları yalnızca kanalı belirler (Hr_S_LeaveRequestAfterSave yazar)."
|
||||
},
|
||||
{
|
||||
"Id": "8de88689-3dde-5ed9-b41f-a8bb287e7094",
|
||||
"Name": "TeklifTalebiGonderildi",
|
||||
"Description": "Satınalma teklif talebi tedarikçiye gönderildiğinde tetiklenir (Teklif Talepleri › İşlem = Gönder / İhaleyi Gönder). Alıcı tedarikçinin kontak e-postasıdır; mesaj kalemleri, miktarları ve istenen terminleri taşır, fiyat içermez. Bu tipin Custom Mail kuralı gönderimi açar (Prc_P_PurchaseRfqSend yazar)."
|
||||
},
|
||||
{
|
||||
"Id": "bbb44959-fb0b-56f8-9b63-693f6480b45d",
|
||||
"Name": "SatinalmaSiparisiGonderildi",
|
||||
"Description": "Satınalma siparişi tedarikçiye gönderildiğinde tetiklenir (Satınalma Siparişleri › İşlem = PO Gönder). Alıcı tedarikçinin kontak e-postasıdır; mesaj kalemleri, fiyatları, terminleri ve toplamı taşır. Bu tipin Custom Mail kuralı gönderimi açar (Prc_P_PurchaseOrderSend yazar)."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,19 +157,24 @@ Yönetim › Tanımlamalar › Onaycılar (onay yeri Satınalma); Yönetim › R
|
|||
|
||||
### 1. Amaç ve kapsam
|
||||
|
||||
Satınalma ekibinin onaylanmış malzeme taleplerinden tedarikçilere teklif talebi (RFQ) açması, gelen teklifi işlemesi, teklifi satınalma siparişine çevirmesi ve tedarikçiyle çerçeve sözleşme (kapsamlı sipariş / ihale) yönetmesi. Kullanıcılar satınalma personeli ve alıcılardır. Mal kabul (makbuz), tedarikçi faturası, alınan/faturalanan miktar takibi ve analitik dağılım kapsam dışıdır.
|
||||
Satınalma ekibinin onaylanmış malzeme taleplerinden tedarikçilere teklif talebi (RFQ) açması, aynı ihtiyacı birden fazla tedarikçiye sorarak ihale gibi fiyat toplaması, gelen fiyat ve terminleri kıyaslayıp en uygun teklifi kalem bazında satınalma siparişine dönüştürmesi; gerekirse teklif toplamadan doğrudan sipariş yazması ve tedarikçiyle çerçeve sözleşme yönetmesi. Kullanıcılar satınalma personeli ve alıcılardır. Tedarikçinin linkten kendi fiyatını girdiği portal, mal kabul (alınan/kalan miktar), tedarikçi faturası (faturalanan, Fatura Yükle) ve analitik dağılım kapsam dışıdır.
|
||||
|
||||
### 2. Analiz ve kararlar
|
||||
|
||||
- Teklif talebi ve satınalma siparişi tek belgedir (`Prc_T_PurchaseOrder`); numara aşamalar boyunca korunur. Durum: Draft (Teklif Talebi) › Sent (Gönderildi) › Purchase (Satınalma Siparişi) / Cancelled.
|
||||
- Numaratörler: `PurchaseOrder1` (P00001), `PurchaseAgreement1` (BO00001).
|
||||
- Firma kolonu açılmadı (kiracı kapsamı). Bakım Talebi, Mali Durum, Analitik Dağılım, Alınan/Kalan/Faturalanan, Faturalama Durumu ve Fatura Yükle kullanıcı kararıyla kapsam dışı.
|
||||
- Vergi kalemde tek oran (%); ürünün `PurchaseTaxRate`'inden gelir.
|
||||
- Platformda buton yordam çağıramadığı için durum işlemleri formdaki **İşlem** alanıyla (`PendingAction`) yapılır; kayıtta çalışır ve alan temizlenir. "Talepten Aktar" da formdaki Malzeme Talebi alanı + kaydet ile çalışır.
|
||||
- Gönderim: tedarikçinin kontak e-postasına platform bildirim kuyruğu (`Adm_T_Notification`, kanal Mail) üzerinden; kalemler e-posta gövdesinde tablo olarak gider (kuyruk ek dosya taşımaz).
|
||||
- Talep ilişkisi kalem düzeyinde (`MaterialRequestItemId`); aktarım kopyalamadır, talep değişmez; iptal olmayan başka belgede yer alan kalem tekrar aktarılmaz.
|
||||
- Sözleşme seçilen boş teklif, sözleşmenin kalan (sipariş edilmemiş) miktarlarıyla dolar.
|
||||
- Widget'lar: OTD % tüm zamanlar üzerinden; "Sipariş Verilecek Günler" kartı üretilmedi (iki sağlayıcıda ortak tarih farkı yok). Demo veri girilmedi.
|
||||
- Teklif talebi ve satınalma siparişi **ayrı belgelerdir** (`Prc_T_PurchaseRfq`, `Prc_T_PurchaseOrder`), ayrı numaratörle: `PurchaseRfq` (RFQ00001) ve `PurchaseOrder1` (P00001). Sözleşme `PurchaseAgreement1` (BO00001).
|
||||
- **Tedarikçi başına bir teklif belgesi.** Aynı ihtiyaç için açılan belgeler bir ihaledir: `TenderGroupId` ihalenin kök (ilk) belgesinin Id'sidir. Alternatif tedarikçi belgenin **Teklifler** sekmesinde Ekle + tedarikçi seçimiyle eklenir; o anki kalemleriyle birlikte kopya belge açılır (fiyat tedarikçinin fiyat listesinden, para birimi ve koşullar kontak kartından). Bir tedarikçi ihalede bir kez bulunur.
|
||||
- Bir teklif birden fazla malzeme talebinden oluşabilir: belgenin **Talep Kalemleri** sekmesi aktarılabilir bütün talep kalemlerini talebe göre gruplu listeler; toplu düzenleme (batch) modunda istenen satırlarda Aktar işaretlenip tek Kaydet ile kopyalanır. Aynı sekme teklifsiz yazılan taslak siparişte de vardır. Talep ilişkisi kalem düzeyindedir (`MaterialRequestItemId`).
|
||||
- Popup (Yeni/Düzenle) formu yalnız belgenin kendi alanlarını taşır; talep aktarımı, alternatif, fiyat girişi ve durum işlemleri liste araç çubuğundaki butonlardadır (sekmelerden de yapılabilir). Vergi hariç / KDV / toplam kalemlerden hesaplandığı için formda değil listede görünür.
|
||||
- Hızlı fiyat girişi: **Fiyat Karşılaştırması** sekmesi toplu düzenleme modundadır; ihalenin bütün tedarikçilerinin birim fiyat, teslim tarihi ve Seçili değerleri tek tabloda satır içinde yazılıp birlikte kaydedilir.
|
||||
- Araç çubuğu butonları ListForm'un Commands (özel buton) kaydıyla, `OnClick` modunda yazılır; çekirdek değişmez. Talepten Aktar `PurchaseRequestImport`, Alternatif Oluştur `PurchaseRfqAlternative` diyaloğunu (kullanıcı onayıyla eklenen iki Satınalma modalı, `ui/src/views/purchasing`) seçili satırla açar. Modallar belgenin sekme ekranlarını (`App.Prc.*ImportItem`, `App.Prc.PurchaseRfqAlternative`, `App.Prc.PurchaseRfqComparison`) platformun Grid bileşeniyle gösterir; ayrı bir uç yoktur.
|
||||
- Teklif durumları: Taslak (Teklif Talebi) › Teklif Talebi Gönderildi (tedarikçiye e-posta kuyruğa alındı) › Satınalma Siparişi (dönüştürüldü) / İptal Edildi. Sipariş durumları: Taslak › Onaylandı / İptal; tekliften dönüşen sipariş onaylı açılır.
|
||||
- **Kıyas (Fiyat Karşılaştırması):** fiyat `Sas_H_Currency.Rate` ile TL'ye çevrilir (kur = 1 birimin TL karşılığı). Puan = Fiyat ağırlığı × (en düşük TL fiyat / TL fiyat) + Termin ağırlığı × (en kısa termin günü / termin günü); termin günü = teslim tarihi − ihalenin açılış günü (en az 1). Ağırlıklar ihale genelinde tektir, varsayılan %70 fiyat / %30 termin, toplamı 100 olmalıdır. En yüksek puan **Önerilen**'dir. Fiyatı 0, terminsiz, "Teklif Verilmedi" ya da iptal edilmiş belgenin satırı puanlanmaz. Kalemin teslim tarihi boşsa belgenin Beklenen Geliş'i kullanılır.
|
||||
- **Siparişe Dönüştür kalem bazındadır** (ihale genelinde, ihaledeki herhangi bir belgeden): kalemin **Seçili** satırı varsa o, yoksa Önerilen satır kazanır. Kazanan her teklif belgesi için ayrı satınalma siparişi açılır; en az bir kalem kazanan teklif Satınalma Siparişi, hiç kazanamayan teklif İptal Edildi olur.
|
||||
- **Kaynak** kolonu: teklifte kalemlerin talep numaraları; tekliften dönüşen siparişte teklif talep no; doğrudan yazılan siparişte talep numaraları.
|
||||
- Durum butonları (Gönder, İhaleyi Gönder, Siparişe Dönüştür, Siparişi Onayla, İptal, Taslak olarak ayarla) onay sorar, işlemi gizli `PendingAction` alanına yazıp ekranın kendi güncelleme ucuyla (`list-form-data/update`) kaydeder; kayıt sonrası yordam işlemi `Prc_P_*SetStatus` ile çalıştırır ve alanı temizler. Alan formda görünmez.
|
||||
- E-posta, bildirim kuyruğundan (`Adm_T_Notification`, kanal Mail) tedarikçinin kontak e-postasına gider; teklif e-postası fiyat içermez (ürün, miktar, istenen termin, teklif son tarihi), sipariş e-postası fiyatlı. Kuyruk mesajı 2048 karakterle sınırlıdır; çok kalemli belgede tablo kısalır.
|
||||
- SQL tarafında açılan belgelerin (alternatif teklif, dönüşen sipariş) numarası numaratörden `Adm_P_SequenceNext` ile alınır; biçim `Sequence.GetNextSequence` ile aynıdır.
|
||||
- Kullanıcı kararıyla kapsam dışı: tedarikçi portalı (fiyatı satınalma girer), Alınan/Kalan/Faturalanan ve Fatura Yükle. Firma kolonu açılmadı (kiracı kapsamı). Demo veri girilmedi.
|
||||
|
||||
### 3. Menü ve ekranlar
|
||||
|
||||
|
|
@ -177,62 +182,69 @@ Satınalma (`App.Prc`) › Siparişler (`App.Prc.Orders`):
|
|||
|
||||
| Ekran | Kod | Not |
|
||||
| --- | --- | --- |
|
||||
| Sözleşmeler | `App.Prc.PurchaseAgreement` | sekme: Ürünler; satırda Yeni Teklif (Teklif Talepleri'ni açar) |
|
||||
| Teklif Talepleri | `App.Prc.PurchaseRfq` | tüm durumlar; sekmeler Ürünler, Tedarikçi Teklifi, Diğer Bilgiler, Teklifler |
|
||||
| Satınalma Siparişleri | `App.Prc.PurchaseOrder` | Status = Purchase; ekle/sil kapalı; sekmeler Ürünler, Diğer Bilgiler, Teklifler |
|
||||
| Sözleşmeler | `App.Prc.PurchaseAgreement` | sekme: Ürünler |
|
||||
| Teklif Talepleri | `App.Prc.PurchaseRfq` | tüm durumlar; sekmeler Ürünler, Talep Kalemleri, Tedarikçi Teklifi, Diğer Bilgiler, Teklifler (Ekle = alternatif), Fiyat Karşılaştırması (toplu düzenleme) |
|
||||
| Satınalma Siparişleri | `App.Prc.PurchaseOrder` | tüm durumlar; ekle/sil (yalnız teklifsiz taslak); sekmeler Ürünler, Talep Kalemleri, Diğer Bilgiler, Teklifler |
|
||||
|
||||
Menüsüz alt formlar: `App.Prc.PurchaseAgreementLine`, `App.Prc.PurchaseOrderLine`, `App.Prc.PurchaseOrderQuote`, `App.Prc.PurchaseOrderOther`, `App.Prc.PurchaseOrderAlternative`.
|
||||
Menüsüz alt formlar: teklif tarafında `App.Prc.PurchaseRfqLine`, `App.Prc.PurchaseRfqImportItem`, `App.Prc.PurchaseRfqQuote`, `App.Prc.PurchaseRfqOther`, `App.Prc.PurchaseRfqAlternative`, `App.Prc.PurchaseRfqComparison`; sipariş tarafında `App.Prc.PurchaseOrderLine`, `App.Prc.PurchaseOrderImportItem`, `App.Prc.PurchaseOrderOther`, `App.Prc.PurchaseOrderAlternative`; sözleşmede `App.Prc.PurchaseAgreementLine`.
|
||||
|
||||
### 4. Veri modeli
|
||||
|
||||
Tüm tablolar kiracı + tam audit + soft delete.
|
||||
|
||||
- `Prc_T_PurchaseAgreement`: AgreementNo, SupplierId, BuyerUserId, AgreementType (Blanket/Tender), CurrencyId, StartDate, EndDate, Reference, OperationTypeId, Terms, Status (Draft/Confirmed/Closed/Cancelled).
|
||||
- `Prc_T_PurchaseAgreementLine`: AgreementId (FK cascade), ProductId, Description, Quantity, UomId, UnitPrice.
|
||||
- `Prc_T_PurchaseOrder`: OrderNo, SupplierId, SupplierReference, AgreementId, MaterialRequestId (aktarım seçimi, kayıttan sonra boşalır), CurrencyId, OrderDeadline, ExpectedArrival, RequireConfirmation, OperationTypeId, ConfirmDate, ArrivalDate, SupplierResponse, QuoteDate, QuotedByUserId, QuoteValidUntil, BuyerUserId, SourceDocument, ProjectId, IncotermId, IncotermLocation, PaymentTermId, Terms, UntaxedAmount, TaxAmount, TotalAmount, Status, PendingAction, LastSentDate.
|
||||
- `Prc_T_PurchaseOrderLine`: PurchaseOrderId (FK cascade), ProductId, Description, Quantity, UomId, UnitPrice, TaxRate, Amount, MaterialRequestItemId.
|
||||
- Görünümler: `Prc_V_PurchaseAgreementLine` (OrderedQuantity), `Prc_V_PurchaseOrderAlternative` (Teklifler sekmesi), `Prc_V_MaterialRequestImportable` (aktarılabilir talepler).
|
||||
- Yordamlar: `Prc_P_PurchaseOrderAfterSave`, `Prc_P_PurchaseOrderRecalc`, `Prc_P_PurchaseOrderImportRequest`, `Prc_P_PurchaseRfqFromAgreement`, `Prc_P_PurchaseOrderSetStatus`, `Prc_P_PurchaseOrderSend`.
|
||||
- `Prc_T_PurchaseRfq`: RfqNo, TenderGroupId, SupplierId, SupplierReference, AgreementId, CurrencyId, OrderDeadline, ExpectedArrival, RequireConfirmation, OperationTypeId, SupplierResponse (Waiting/Quoted/NotQuoted), QuoteDate, QuoteValidUntil, BuyerUserId, SourceDocument, ProjectId, IncotermId, IncotermLocation, PaymentTermId, Terms, PriceWeight (70), DeliveryWeight (30), UntaxedAmount, TaxAmount, TotalAmount, Status (Draft/Sent/Purchase/Cancelled), PendingAction, LastSentDate.
|
||||
- `Prc_T_PurchaseRfqLine`: PurchaseRfqId (FK cascade), TenderLineId (alternatiflerde aynı kalemi eşler), ProductId, Description, Quantity, UomId, UnitPrice, TaxRate, Amount, DeliveryDate (tedarikçinin termini; aktarımda talebin istenen termini), MaterialRequestItemId, IsSelected.
|
||||
- `Prc_T_PurchaseOrder`: OrderNo, PurchaseRfqId (kaynak teklif), SupplierId, SupplierReference, AgreementId, CurrencyId, ExpectedArrival, OperationTypeId, ConfirmDate, ArrivalDate, BuyerUserId, SourceDocument, ProjectId, IncotermId, IncotermLocation, PaymentTermId, Terms, tutarlar, Status (Draft/Purchase/Cancelled), PendingAction, LastSentDate.
|
||||
- `Prc_T_PurchaseOrderLine`: PurchaseOrderId (FK cascade), ProductId, Description, Quantity, UomId, UnitPrice, TaxRate, Amount, DeliveryDate, MaterialRequestItemId, PurchaseRfqLineId.
|
||||
- Görünümler: `Prc_V_MaterialRequestAvailableItem` (aktarılabilir talep kalemleri), `Prc_V_PurchaseImportItem` (Talep Kalemleri sekmesi: kalem alabilen açık belge × aktarılabilir kalem, `Id` = belge|kalem), `Prc_V_PurchaseRfqComparison` (kıyas ve puan), `Prc_V_PurchaseRfqAlternative` (ihalenin belgeleri; teklif ve sipariş için `BaseId`), `Prc_V_PurchaseAgreementLine` (sözleşmenin sipariş edilen miktarı).
|
||||
- Yordamlar: `Prc_P_PurchaseRfq{AfterSave,Recalc,CreateAlternative,FromAgreement,Send,SetStatus,Award}`, `Prc_P_PurchaseOrder{AfterSave,Recalc,Send,SetStatus}`, `Prc_P_PurchaseImportItem` (teklif ve sipariş için ortak, kalem bazlı aktarım), `Adm_P_SequenceNext`.
|
||||
|
||||
### 5. İş kuralları ve hesaplar
|
||||
|
||||
- Kayıt sonrası `Prc_P_PurchaseOrderAfterSave`: boş ödeme/teslimat koşulu ve Incoterm konumu tedarikçinin Satınalma sekmesinden dolar (alıcı yalnız ilk kayıtta); sözleşme seçili ve kalem yoksa sözleşme kalemleri; Malzeme Talebi seçiliyse aktarım; tutarlar; İşlem.
|
||||
- Tutar = Miktar × Birim Fiyat; KDV = Σ(Tutar × Oran/100); Toplam = Vergi Hariç + KDV. Kalem her eklenip/değişip/silindiğinde yeniden hesaplanır. Kaynak, kalemlerin talep numaralarıdır.
|
||||
- Aktarım: talep Onaylandı; kalem Karşılama = Satınalma, Durum = Bekliyor; başka iptal olmayan belgede olmayan kalemler. Fiyat: sözleşme kalemi › tedarikçi fiyatı (`Inv_T_ProductSupplier`) › 0. Aktarılacak kalem yoksa hata.
|
||||
- İşlemler: Gönder (iptal dışında; kalem ve tedarikçi e-postası şart; Draft ise Sent olur, LastSentDate yazılır) · Siparişi Onayla (Draft/Sent → Purchase, ConfirmDate) · İptal · Taslak olarak ayarla (yalnız Cancelled → Draft).
|
||||
- İptal edilmiş belge değiştirilemez (Taslak işlemi hariç), kalem eklenemez/silinemez. Gönderilmiş teklif ve sipariş silinemez.
|
||||
- Tedarikçi Teklifi'nde yanıt Bekleniyor dışına alınınca boş teklif tarihi ve teklifi veren dolar.
|
||||
- Sözleşmede bitiş tarihi başlangıçtan önce olamaz.
|
||||
- Teklif kaydı ve Tedarikçi Teklifi / Diğer Bilgiler sekmesindeki kayıt sonrası `Prc_P_PurchaseRfqAfterSave`: ağırlık toplamı 100 kontrolü; boş ödeme/teslimat koşulu ve Incoterm konumu tedarikçinin Satınalma sekmesinden (alıcı yalnız ilk kayıtta); yanıt Bekleniyor dışına alınınca boş teklif tarihi; ağırlıkların ihalenin diğer belgelerine yazılması; sözleşme kalemleri (yalnız kalemsiz belgede); tutarlar; buton işlemi (`PendingAction`).
|
||||
- Aktarım (`Prc_P_PurchaseImportItem`, işaretlenen her satır için): belge teklif aşamasında (teklif) ya da taslak (sipariş); talep Onaylandı; kalem Karşılama = Satınalma, Durum = Bekliyor; iptal olmayan bir teklifte ya da siparişte yer almıyor. Fiyat: sözleşme kalemi › tedarikçi fiyatı (`Inv_T_ProductSupplier`) › 0. Kalem bu arada başka belgeye geçmişse hata.
|
||||
- Alternatif (`Prc_P_PurchaseRfqCreateAlternative`): belge teklif aşamasında olmalı; tedarikçinin ihalede iptal olmayan belgesi varsa hata.
|
||||
- Tutar = Miktar × Birim Fiyat; KDV = Σ(Tutar × Oran/100); Toplam = Vergi Hariç + KDV. Kalem her eklenip/değişip/silindiğinde yeniden hesaplanır.
|
||||
- Teklif işlemleri: E-posta ile Gönder (taslak ya da gönderilmiş; kalem ve tedarikçi e-postası şart; Taslak → Gönderildi) · İhaleyi Gönder (ihalenin bütün taslak belgeleri) · Siparişe Dönüştür (taslak ya da gönderilmiş; ihale daha önce dönüştürülmemiş olmalı) · İptal (siparişe dönüşmüş teklif iptal edilemez) · Taslak olarak ayarla (yalnız iptalden; ihale siparişe dönüşmüşse olmaz).
|
||||
- Sipariş işlemleri: Siparişi Onayla (taslak, kalemli) · E-posta ile Gönder (iptal dışında) · İptal · Taslak olarak ayarla (yalnız iptalden).
|
||||
- Siparişe dönüşmüş ya da iptal edilmiş teklif ve kalemleri değiştirilemez; iptal edilmiş siparişin kalemi değiştirilemez. Gönderilmiş ya da dönüşmüş teklif silinemez; yalnız teklifsiz yazılmış taslak sipariş silinebilir.
|
||||
- Fiyat Karşılaştırması sekmesinde birim fiyat, teslim tarihi ve Seçili düzenlenir (ilgili teklifin toplamı yeniden hesaplanır). Siparişe dönüşte kazanan satırlar Seçili olarak işaretlenir.
|
||||
- Sözleşmede bitiş tarihi başlangıçtan önce olamaz; sözleşme seçilen boş teklif kalan (siparişe dönüşmemiş) miktarlarla dolar.
|
||||
|
||||
### 6. Yetki ve görünürlük
|
||||
|
||||
Yetki ağacı: `App.Prc` › `App.Prc.Orders` › her liste (+ Create/Update/Delete/Export/Import/Note). Alt formların yetkisi taşıyan listenin altındadır; ortak sekmeler (Ürünler, Diğer Bilgiler, Teklifler) Teklif Talepleri'nin altına bağlandı — Satınalma Siparişleri kullanıcılarına bu sekme yetkileri de verilmelidir. Kiracı kapsamlı, şube filtresi yok.
|
||||
Yetki ağacı: `App.Prc` › `App.Prc.Orders` › her liste (+ Create/Update/Delete/Export/Import/Note). Her alt formun yetkisi kendi listesinin altındadır: teklif sekmeleri `App.Prc.PurchaseRfq`, sipariş sekmeleri `App.Prc.PurchaseOrder` altında; sekmeler ekranlar arasında paylaşılmaz. Teklif kullanıcısına Fiyat Karşılaştırması'nın Update yetkisi de verilmelidir (fiyat ve seçim buradan girilir). Yetkiler hiçbir role otomatik atanmaz. Kiracı kapsamlı, şube filtresi yok.
|
||||
|
||||
### 7. Entegrasyonlar
|
||||
|
||||
Yönetim › Tanımlamalar › Kontaklar (tedarikçi, e-posta, Satınalma sekmesi varsayılanları); Envanter (Ürünler, tedarikçi fiyatları, Operasyon Türleri); Satınalma › Tanımlamalar (Ödeme Koşulları, Teslimat Koşulları); Proje modülü (Proje); Malzeme Talepleri (aktarım); Bildirimler (`Prc.RfqSent`, `Prc.PurchaseOrderSent`; NotificationWorker kuyruğu gönderir); Diziler.
|
||||
Yönetim › Tanımlamalar › Kontaklar (tedarikçi, e-posta, Satınalma sekmesi varsayılanları); Envanter (Ürünler, tedarikçi fiyatları, Operasyon Türleri); Satınalma › Tanımlamalar (Ödeme Koşulları, Teslimat Koşulları); Proje modülü; Malzeme Talepleri (aktarım); Para Birimleri (kur); Bildirimler: tipler `TeklifTalebiGonderildi`, `SatinalmaSiparisiGonderildi`, her birinin Custom/Mail kuralı (kural kapatılırsa e-posta kuyruğa girmez; NotificationWorker gönderir); Diziler (`PurchaseRfq`, `PurchaseOrder1`, `PurchaseAgreement1`).
|
||||
|
||||
### 8. Akış örneği
|
||||
|
||||
1. Ali'nin SRO00015 talebi onaylanır (2 satınalma kalemi).
|
||||
2. Satınalma Teklif Talepleri'nde yeni kayıt açar, tedarikçi "3K Kutu" seçer (para birimi ve koşullar dolar), Talepten Aktar'da SRO00015'i seçip kaydeder; iki kalem fiyatlarıyla gelir, Kaynak = SRO00015.
|
||||
3. İşlem = E-posta ile Gönder, kaydet: tedarikçiye e-posta kuyruğa alınır, durum Gönderildi.
|
||||
4. Tedarikçi Teklifi sekmesinde yanıt = Teklif Verildi; fiyatlar Ürünler sekmesinde güncellenir.
|
||||
5. İşlem = Siparişi Onayla: belge Satınalma Siparişleri'ne düşer; gerekirse İşlem = E-posta ile Gönder ile PO gönderilir. Mal gelince Varış girilir.
|
||||
1. Ali'nin MT-2026-00015 ve Ayşe'nin MT-2026-00016 talepleri onaylanır.
|
||||
2. Satınalma Teklif Talepleri'nde yeni kayıt açar (tedarikçi "3K Kutu"), kaydeder; detayda Talep Kalemleri sekmesinde iki talebin kalemlerini işaretleyip Kaydet der. Teklifler sekmesinde Ekle ile "5 Mutlu Gıda" ve "Kartela"yı ekler. RFQ00001 (3K) kalemleriyle, RFQ00002 ve RFQ00003 kopya olarak aynı ihalede açılır; Kaynak = MT-2026-00015, MT-2026-00016.
|
||||
3. Araç çubuğunda İhaleyi Gönder: üç tedarikçiye fiyatsız teklif e-postası kuyruğa alınır, belgeler Gönderildi olur.
|
||||
4. Tedarikçilerin dönüşleri Fiyat Karşılaştırması sekmesinde tek tabloda birim fiyat ve teslim tarihi olarak yazılıp bir kez kaydedilir; her ürün için en yüksek puanlı satır Önerilen işaretlenir. Kullanıcı bir üründe daha pahalı ama güvendiği tedarikçiyi Seçili yapar.
|
||||
5. Siparişe Dönüştür butonu: kazanan iki tedarikçiye P00007 ve P00008 açılır (Kaynak RFQ00001 / RFQ00003), RFQ00002 İptal Edildi olur.
|
||||
6. Satınalma Siparişleri'nde E-posta ile Gönder butonuyla siparişler tedarikçiye gider; mal gelince Varış girilir.
|
||||
|
||||
### 9. Sık sorulanlar
|
||||
|
||||
- **Butonlar nerede?** Durum işlemleri formdaki İşlem alanındadır; seçip kaydedin.
|
||||
- **Talep listede çıkmıyor?** Talep onaylanmış olmalı ve aktarılabilir (Satınalma, Bekliyor, başka belgede olmayan) kalemi bulunmalı.
|
||||
- **E-posta gitmedi?** Tedarikçinin kontak e-postasını ve Bildirimler ekranındaki satırı (IsSent) kontrol edin; NotificationWorker aktif olmalı.
|
||||
- **Sözleşme seçince kalem gelmedi?** Yalnız kalemi olmayan belgeye ve kalan miktarı olan sözleşme kalemleri gelir.
|
||||
- **Butonlar nerede?** Listede bir belge seçilir; işlemler araç çubuğundadır (detay sayfasının araç çubuğunda da görünür). Buton yetkisi: durum işlemleri ekranın Update, Talepten Aktar ilgili Talep Kalemleri ekranının Update, Alternatif Oluştur Teklifler ekranının Create yetkisi.
|
||||
- **Talep Kalemleri sekmesi boş?** Talep onaylanmış olmalı ve aktarılabilir (Satınalma, Bekliyor, başka açık teklifte ya da siparişte olmayan) kalemi bulunmalı; belge Teklif Talebi / Gönderildi (sipariş için Taslak) durumunda olmalı.
|
||||
- **Talepten Aktar / Alternatif Oluştur modalı nasıl kullanılır?** Talepten Aktar'da aktarılacak satırlarda Aktar işaretlenip tablonun Kaydet'ine basılır. Alternatif Oluştur'da Tedarikçiler sekmesinde Ekle ile tedarikçi seçilir, Fiyat Girişi sekmesinde bütün tedarikçilerin fiyat ve terminleri yazılıp Kaydet'e basılır.
|
||||
- **Alternatif ekledim, kalemleri eksik?** Alternatif, açıldığı andaki kalemleri kopyalar; sonradan eklenen kalem yalnız eklendiği belgededir.
|
||||
- **Önerilen neden boş?** Satırın fiyatı ve teslim tarihi (ya da belgenin Beklenen Geliş'i) girilmiş olmalı; Teklif Verilmedi yanıtlı ya da iptal edilmiş belge kıyasa girmez.
|
||||
- **E-posta gitmedi?** Tedarikçinin kontak e-postasını, Bildirim Kuralları'nda ilgili tipin Mail kuralını ve Bildirimler ekranındaki satırı (IsSent) kontrol edin; NotificationWorker aktif olmalı.
|
||||
- **Farklı para birimindeki teklif nasıl kıyaslanıyor?** Para Birimleri ekranındaki kurla TL'ye çevrilerek; kur güncel değilse kıyas yanıltır.
|
||||
|
||||
### 10. Dosyalar ve geri alma
|
||||
|
||||
- Tablolar: `sql/object/Prc_T_PurchaseAgreement.sql`, `Prc_T_PurchaseAgreementLine.sql`, `Prc_T_PurchaseOrder.sql`, `Prc_T_PurchaseOrderLine.sql` (+ postgres).
|
||||
- Görünüm/yordam: `Prc_V_PurchaseAgreementLine`, `Prc_V_PurchaseOrderAlternative`, `Prc_V_MaterialRequestImportable`, `Prc_P_PurchaseOrder{AfterSave,Recalc,ImportRequest,SetStatus,Send}`, `Prc_P_PurchaseRfqFromAgreement` (sql + postgres object).
|
||||
- Wizard'lar: `Prc_PurchaseAgreementLine.json`, `Prc_PurchaseAgreement.json`, `Prc_PurchaseOrderLine.json`, `Prc_PurchaseOrderQuote.json`, `Prc_PurchaseOrderOther.json`, `Prc_PurchaseOrderAlternative.json`, `Prc_PurchaseRfq.json`, `Prc_PurchaseOrder.json`.
|
||||
- Veri: Diziler `PurchaseOrder1`, `PurchaseAgreement1`; Bildirim Türleri `Prc.RfqSent`, `Prc.PurchaseOrderSent`.
|
||||
- Tablolar: `sql/object/Prc_T_PurchaseRfq.sql`, `Prc_T_PurchaseRfqLine.sql`, `Prc_T_PurchaseOrder.sql`, `Prc_T_PurchaseOrderLine.sql`, `Prc_T_PurchaseAgreement.sql`, `Prc_T_PurchaseAgreementLine.sql` (+ postgres).
|
||||
- Görünüm/yordam: `Prc_V_MaterialRequestAvailableItem`, `Prc_V_PurchaseImportItem`, `Prc_V_PurchaseRfqComparison`, `Prc_V_PurchaseRfqAlternative`, `Prc_V_PurchaseAgreementLine`, `Prc_P_PurchaseRfq*`, `Prc_P_PurchaseOrder*`, `Prc_P_PurchaseImportItem`, `Adm_P_SequenceNext` (sql + postgres object).
|
||||
- Wizard'lar: `Prc_PurchaseRfq{,Line,ImportItem,Quote,Other,Alternative,Comparison}.json`, `Prc_PurchaseOrder{,Line,ImportItem,Other,Alternative}.json`, `Prc_PurchaseAgreement{,Line}.json`.
|
||||
- Arayüz: `ui/src/views/purchasing/PurchaseRequestImportDialog.tsx`, `PurchaseRfqAlternativeDialog.tsx` (kayıt: `DialogShowComponent`).
|
||||
- Veri: Diziler `PurchaseRfq`, `PurchaseOrder1`, `PurchaseAgreement1`; Bildirim Türleri ve Kuralları `TeklifTalebiGonderildi`, `SatinalmaSiparisiGonderildi`.
|
||||
- Geri alma: önce ana ekranlar (`Prc_PurchaseRfq`, `Prc_PurchaseOrder`, `Prc_PurchaseAgreement`), sonra alt formlar `delete_wizard` ile silinir; tablolar yalnız açık onayla düşürülür.
|
||||
|
||||
<!-- module-doc:auto:begin -->
|
||||
|
|
@ -585,39 +597,40 @@ Yönetim › Tanımlamalar › Kontaklar (tedarikçi, e-posta, Satınalma sekmes
|
|||
| Yol | Liste (Wizard) |
|
||||
| Menü | `App.Prc.Orders` › `App.Prc.PurchaseRfq` (sıra 2) |
|
||||
| Yetki | `App.Prc.PurchaseRfq` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||
| Açıklama | Teklif Talepleri — her durumdaki satınalma belgeleri: Teklif Talebi, Teklif Talebi Gönderildi, Satınalma Siparişi ve İptal Edildi. |
|
||||
| Açıklama | Teklif Talepleri — her tedarikçi için ayrı satınalma belgesi; aynı ihtiyaç için açılan belgeler bir ihale oluşturur ve siparişten önce kıyaslanır. |
|
||||
| Geliştirme talebi | Satınalma -> Siparişler |
|
||||
| Kaynak | `Prc_T_PurchaseOrder` · filtre `"IsDeleted" = 'false'` |
|
||||
| Kaynak | `Prc_T_PurchaseRfq` · filtre `"IsDeleted" = 'false'` |
|
||||
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||
| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup |
|
||||
| Kapsam | Kiracı |
|
||||
| Alt formlar | `App.Prc.PurchaseOrderLine` (Id → PurchaseOrderId), `App.Prc.PurchaseOrderQuote` (Id → Id), `App.Prc.PurchaseOrderOther` (Id → Id), `App.Prc.PurchaseOrderAlternative` (Id → BaseOrderId) |
|
||||
| Widget'lar | `App.Prc.OrderStatus.Draft`, `App.Prc.OrderStatus.Sent`, `App.Prc.PurchaseOrder.Widget.LateRfq`, `App.Prc.PurchaseOrder.Widget.NotAcknowledged`, `App.Prc.PurchaseOrder.Widget.LateReceipt`, `App.Prc.PurchaseOrder.Widget.Otd` |
|
||||
| Komutlar | InsertAfter: `Prc_P_PurchaseOrderAfterSave` · UpdateBefore: SQL · UpdateAfter: `Prc_P_PurchaseOrderAfterSave` · DeleteBefore: SQL |
|
||||
| Form varsayılanları | OrderNo=PurchaseOrder1, BuyerUserId=@USERID, CurrencyId=TRY, RequireConfirmation=false, Status=Draft |
|
||||
| Alt formlar | `App.Prc.PurchaseRfqLine` (Id → PurchaseRfqId), `App.Prc.PurchaseRfqImportItem` (Id → BaseId), `App.Prc.PurchaseRfqQuote` (Id → Id), `App.Prc.PurchaseRfqOther` (Id → Id), `App.Prc.PurchaseRfqAlternative` (Id → BaseId), `App.Prc.PurchaseRfqComparison` (Id → BaseId) |
|
||||
| Widget'lar | `App.Widget.Draft`, `App.Widget.Sent`, `App.Widget.Expired`, `App.Widget.Completed` |
|
||||
| Komutlar | InsertAfter: `Prc_P_PurchaseRfqAfterSave` · UpdateBefore: SQL · UpdateAfter: `Prc_P_PurchaseRfqAfterSave` · DeleteBefore: SQL |
|
||||
| Form varsayılanları | RfqNo=PurchaseRfq, BuyerUserId=@USERID, CurrencyId=TRY, RequireConfirmation=false, Status=Draft |
|
||||
| Butonlar | `App.Prc.PurchaseRfq.ImportRequests`, `App.Prc.PurchaseRfq.CreateAlternative`, `App.Prc.PurchaseOrder.Action.Send`, `App.Prc.PurchaseRfq.Action.SendTender`, `App.Prc.PurchaseRfq.Action.Award`, `App.Prc.PurchaseOrder.Action.Cancel`, `App.Prc.PurchaseOrder.Action.Draft` |
|
||||
|
||||
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `OrderNo` | Referans | dxTextBox | ✓ | ✓ | |
|
||||
| `Status` | Durumu | dxSelectBox | ✓ | ✓ | liste: Draft, Sent, Purchase, Cancelled |
|
||||
| `SupplierId` | Tedarikçi | dxSelectBox | ✓ | ✓ | sorgu: Adm_T_Contact · script |
|
||||
| `RfqNo` | Teklif Talep No | dxTextBox | ✓ | ✓ | |
|
||||
| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: Draft, Sent, Purchase, Cancelled |
|
||||
| `OrderDeadline` | Sipariş Zaman Sınırı | dxDateBox | | ✓ | |
|
||||
| `SupplierReference` | Tedarikçi Referansı | dxTextBox | | ✓ | |
|
||||
| `ExpectedArrival` | Beklenen Geliş | dxDateBox | | ✓ | |
|
||||
| `AgreementId` | Sözleşme | dxSelectBox | | ✓ | sorgu: Prc_T_PurchaseAgreement (← SupplierId) |
|
||||
| `RequireConfirmation` | Onay İsteyin | dxCheckBox | | ✓ | |
|
||||
| `CurrencyId` | Para Birimi | dxSelectBox | ✓ | ✓ | sorgu: Sas_H_Currency |
|
||||
| `OperationTypeId` | Teslim Alacak | dxSelectBox | | ✓ | sorgu: Inv_T_OperationType |
|
||||
| `MaterialRequestId` | Talepten Aktar | dxSelectBox | | ✓ | sorgu: Prc_V_MaterialRequestImportable |
|
||||
| `PendingAction` | İşlem | dxSelectBox | | ✓ | liste: Send, Confirm, Cancel, Draft |
|
||||
| `OperationTypeId` | Operasyon Türü | dxSelectBox | | ✓ | sorgu: Inv_T_OperationType |
|
||||
| `PendingAction` | İşlem | dxTextBox | | | |
|
||||
| `TenderGroupId` | İhale | dxSelectBox | | | sorgu: Prc_T_PurchaseRfq |
|
||||
| `SupplierResponse` | Tedarikçi Yanıtı | dxSelectBox | | | liste: Waiting, Quoted, NotQuoted |
|
||||
| `BuyerUserId` | Alıcı | dxSelectBox | | | sorgu: AbpUsers |
|
||||
| `SourceDocument` | Kaynak | dxTextBox | | | |
|
||||
| `UntaxedAmount` | Vergi Hariç Tutar | dxNumberBox | | ✓ | |
|
||||
| `TaxAmount` | KDV | dxNumberBox | | ✓ | |
|
||||
| `TotalAmount` | Toplam | dxNumberBox | | ✓ | |
|
||||
| `BuyerUserId` | Alıcı | dxSelectBox | | | sorgu: AbpUsers |
|
||||
| `UntaxedAmount` | Vergi Hariç Tutar | dxNumberBox | | | |
|
||||
| `TaxAmount` | Vergi Tutarı | dxNumberBox | | | |
|
||||
| `TotalAmount` | Toplam Tutar | dxNumberBox | | | |
|
||||
| `LastSentDate` | Son Gönderim | dxDateBox | | | |
|
||||
| `Terms` | Şart ve Koşullar | dxTextArea | | ✓ | |
|
||||
| `Terms` | Şartlar | dxHtmlEditor | | ✓ | |
|
||||
|
||||
#### Satınalma Siparişleri — `App.Prc.PurchaseOrder`
|
||||
|
||||
|
|
@ -627,38 +640,38 @@ Yönetim › Tanımlamalar › Kontaklar (tedarikçi, e-posta, Satınalma sekmes
|
|||
| Yol | Liste (Wizard) |
|
||||
| Menü | `App.Prc.Orders` › `App.Prc.PurchaseOrder` (sıra 3) |
|
||||
| Yetki | `App.Prc.PurchaseOrder` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||
| Açıklama | Satınalma Siparişleri — siparişe çevrilmiş teklif talepleri. |
|
||||
| Açıklama | Satınalma Siparişleri — tedarikçilere verilen siparişler; teklif talebi ihalesinden dönüştürülür ya da teklif toplamadan doğrudan yazılır. |
|
||||
| Geliştirme talebi | Satınalma -> Siparişler |
|
||||
| Kaynak | `Prc_T_PurchaseOrder` · filtre `"IsDeleted" = 'false' AND "Status" = 'Purchase'` |
|
||||
| Kaynak | `Prc_T_PurchaseOrder` · filtre `"IsDeleted" = 'false'` |
|
||||
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||
| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup |
|
||||
| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup |
|
||||
| Kapsam | Kiracı |
|
||||
| Alt formlar | `App.Prc.PurchaseOrderLine` (Id → PurchaseOrderId), `App.Prc.PurchaseOrderOther` (Id → Id), `App.Prc.PurchaseOrderAlternative` (Id → BaseOrderId) |
|
||||
| Widget'lar | `App.Prc.PurchaseOrder.Widget.LateReceipt`, `App.Prc.PurchaseOrder.Widget.AwaitingArrival`, `App.Widget.TotalRevenue` |
|
||||
| Komutlar | UpdateAfter: `Prc_P_PurchaseOrderAfterSave` |
|
||||
| Form varsayılanları | CurrencyId=TRY, Status=Draft, UntaxedAmount=0, TaxAmount=0, TotalAmount=0 |
|
||||
| Alt formlar | `App.Prc.PurchaseOrderLine` (Id → PurchaseOrderId), `App.Prc.PurchaseOrderImportItem` (Id → BaseId), `App.Prc.PurchaseOrderOther` (Id → Id), `App.Prc.PurchaseOrderAlternative` (Id → BaseId) |
|
||||
| Widget'lar | `App.Widget.Draft`, `App.Prc.PurchaseOrder.Widget.AwaitingArrival`, `App.Prc.PurchaseOrder.Widget.LateReceipt`, `App.Widget.TotalRevenue` |
|
||||
| Komutlar | InsertAfter: `Prc_P_PurchaseOrderAfterSave` · UpdateBefore: SQL · UpdateAfter: `Prc_P_PurchaseOrderAfterSave` · DeleteBefore: SQL |
|
||||
| Form varsayılanları | OrderNo=PurchaseOrder1, BuyerUserId=@USERID, CurrencyId=TRY, Status=Draft |
|
||||
| Butonlar | `App.Prc.PurchaseRfq.ImportRequests`, `App.Prc.PurchaseOrder.Action.Confirm`, `App.Prc.PurchaseOrder.Action.Send`, `App.Prc.PurchaseOrder.Action.Cancel`, `App.Prc.PurchaseOrder.Action.Draft` |
|
||||
|
||||
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `SupplierId` | Tedarikçi | dxSelectBox | ✓ | ✓ | sorgu: Adm_T_Contact · script |
|
||||
| `OrderNo` | Referans | dxTextBox | ✓ | ✓ | |
|
||||
| `SupplierId` | Tedarikçi | dxSelectBox | ✓ | ✓ | sorgu: Adm_T_Contact |
|
||||
| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: Draft, Purchase, Cancelled |
|
||||
| `ConfirmDate` | Onaylama Tarihi | dxDateBox | | ✓ | |
|
||||
| `ExpectedArrival` | Beklenen Geliş | dxDateBox | | ✓ | |
|
||||
| `SupplierReference` | Tedarikçi Referansı | dxTextBox | | ✓ | |
|
||||
| `ExpectedArrival` | Beklenen Geliş | dxDateBox | | ✓ | |
|
||||
| `AgreementId` | Sözleşme | dxSelectBox | | ✓ | sorgu: Prc_T_PurchaseAgreement (← SupplierId) |
|
||||
| `ArrivalDate` | Varış | dxDateBox | | ✓ | |
|
||||
| `AgreementId` | Sözleşme | dxSelectBox | | ✓ | sorgu: Prc_T_PurchaseAgreement |
|
||||
| `OperationTypeId` | Teslim Alacak | dxSelectBox | | ✓ | sorgu: Inv_T_OperationType |
|
||||
| `CurrencyId` | Para Birimi | dxTextBox | ✓ | ✓ | |
|
||||
| `MaterialRequestId` | Talepten Aktar | dxSelectBox | | ✓ | sorgu: Prc_V_MaterialRequestImportable |
|
||||
| `PendingAction` | İşlem | dxSelectBox | | ✓ | liste: Send, Cancel |
|
||||
| `Status` | Durumu | dxSelectBox | | | liste: Draft, Sent, Purchase, Cancelled |
|
||||
| `BuyerUserId` | Alıcı | dxSelectBox | | | sorgu: AbpUsers |
|
||||
| `CurrencyId` | Para Birimi | dxSelectBox | ✓ | ✓ | sorgu: Sas_H_Currency |
|
||||
| `OperationTypeId` | Operasyon Türü | dxSelectBox | | ✓ | sorgu: Inv_T_OperationType |
|
||||
| `PendingAction` | İşlem | dxTextBox | | | |
|
||||
| `SourceDocument` | Kaynak | dxTextBox | | | |
|
||||
| `UntaxedAmount` | Vergi Hariç Tutar | dxNumberBox | | ✓ | |
|
||||
| `TaxAmount` | KDV | dxNumberBox | | ✓ | |
|
||||
| `TotalAmount` | Toplam | dxNumberBox | | ✓ | |
|
||||
| `BuyerUserId` | Alıcı | dxSelectBox | | | sorgu: AbpUsers |
|
||||
| `UntaxedAmount` | Vergi Hariç Tutar | dxNumberBox | | | |
|
||||
| `TaxAmount` | Vergi Tutarı | dxNumberBox | | | |
|
||||
| `TotalAmount` | Toplam Tutar | dxNumberBox | | | |
|
||||
| `LastSentDate` | Son Gönderim | dxDateBox | | | |
|
||||
| `Terms` | Şart ve Koşullar | dxTextArea | | ✓ | |
|
||||
| `Terms` | Şartlar | dxHtmlEditor | | ✓ | |
|
||||
|
||||
#### Sözleşme Kalemleri — `App.Prc.PurchaseAgreementLine`
|
||||
|
||||
|
|
@ -685,6 +698,174 @@ Yönetim › Tanımlamalar › Kontaklar (tedarikçi, e-posta, Satınalma sekmes
|
|||
| `UnitPrice` | Birim Fiyat | dxNumberBox | ✓ | ✓ | |
|
||||
| `Description` | Açıklama | dxTextArea | | ✓ | |
|
||||
|
||||
#### Teklif Kalemleri — `App.Prc.PurchaseRfqLine`
|
||||
|
||||
| Özellik | Değer |
|
||||
| --- | --- |
|
||||
| Wizard | `wizard/Prc_PurchaseRfqLine.json` |
|
||||
| Yol | Liste (Wizard) |
|
||||
| Menü | Menüsüz (alt form) |
|
||||
| Yetki | `App.Prc.PurchaseRfqLine` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||
| Açıklama | Teklif Kalemleri — teklif talebinin ürünleri ve tedarikçinin her biri için verdiği fiyat ile termin. |
|
||||
| Geliştirme talebi | Satınalma -> Siparişler |
|
||||
| Kaynak | `Prc_T_PurchaseRfqLine` · filtre `"IsDeleted" = 'false'` |
|
||||
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||
| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup |
|
||||
| Kapsam | Kiracı |
|
||||
| Komutlar | InsertBefore: SQL · InsertAfter: `Prc_P_PurchaseRfqRecalc` · UpdateBefore: SQL · UpdateAfter: `Prc_P_PurchaseRfqRecalc` · DeleteBefore: SQL · DeleteAfter: `Prc_P_PurchaseRfqRecalc` |
|
||||
| Form varsayılanları | Quantity=1 |
|
||||
|
||||
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `PurchaseRfqId` | Teklif Talebi | dxTextBox | | | |
|
||||
| `ProductId` | Ürün | dxSelectBox | ✓ | ✓ | sorgu: Inv_T_Product · script |
|
||||
| `Description` | Açıklama | dxTextBox | | ✓ | |
|
||||
| `Quantity` | Miktar | dxNumberBox | ✓ | ✓ | |
|
||||
| `UomId` | Birim | dxSelectBox | ✓ | ✓ | sorgu: Adm_T_Uom |
|
||||
| `UnitPrice` | Birim Fiyat | dxNumberBox | ✓ | ✓ | |
|
||||
| `TaxRate` | Vergi Oran | dxNumberBox | ✓ | ✓ | |
|
||||
| `Amount` | Tutar | dxNumberBox | | ✓ | script |
|
||||
| `DeliveryDate` | Teslim Tarihi | dxDateBox | | ✓ | |
|
||||
| `MaterialRequestItemId` | Talep | dxSelectBox | | ✓ | sorgu: Prc_T_MaterialRequestItem |
|
||||
|
||||
#### Teklif Talep Kalemleri — `App.Prc.PurchaseRfqImportItem`
|
||||
|
||||
| Özellik | Değer |
|
||||
| --- | --- |
|
||||
| Wizard | `wizard/Prc_PurchaseRfqImportItem.json` |
|
||||
| Yol | Liste (Wizard) |
|
||||
| Menü | Menüsüz (alt form) |
|
||||
| Yetki | `App.Prc.PurchaseRfqImportItem` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||
| Açıklama | Teklif Talep Kalemleri — onaylı malzeme taleplerinin henüz teklif istenmemiş kalemleri, açık teklif talebi için listelenir. |
|
||||
| Geliştirme talebi | Satınalma -> Siparişler |
|
||||
| Kaynak | `Prc_V_PurchaseImportItem` |
|
||||
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||
| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · batch |
|
||||
| Kapsam | Kiracı |
|
||||
|
||||
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `BaseId` | Ana Belge | dxTextBox | | | |
|
||||
| `RequestNo` | Talep No | dxTextBox | | | |
|
||||
| `RequesterUserId` | Talep Eden | dxSelectBox | | | sorgu: AbpUsers |
|
||||
| `ProductId` | Ürün | dxSelectBox | | | sorgu: Inv_T_Product |
|
||||
| `Quantity` | Miktar | dxNumberBox | | | |
|
||||
| `UomId` | Birim | dxSelectBox | | | sorgu: Adm_T_Uom |
|
||||
| `DueDate` | Bitiş Tarihi | dxDateBox | | | |
|
||||
| `RequestReason` | Talep Nedeni | dxTextBox | | | |
|
||||
| `Transfer` | Aktar | dxCheckBox | | ✓ | |
|
||||
|
||||
#### Tedarikçi Teklifi — `App.Prc.PurchaseRfqQuote`
|
||||
|
||||
| Özellik | Değer |
|
||||
| --- | --- |
|
||||
| Wizard | `wizard/Prc_PurchaseRfqQuote.json` |
|
||||
| Yol | Liste (Wizard) |
|
||||
| Menü | Menüsüz (alt form) |
|
||||
| Yetki | `App.Prc.PurchaseRfqQuote` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||
| Açıklama | Tedarikçi Teklifi — tedarikçinin teklif talebine verdiği yanıt. |
|
||||
| Geliştirme talebi | Satınalma -> Siparişler |
|
||||
| Kaynak | `Prc_T_PurchaseRfq` · filtre `"IsDeleted" = 'false'` |
|
||||
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||
| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup |
|
||||
| Kapsam | Kiracı |
|
||||
| Komutlar | UpdateBefore: SQL · UpdateAfter: `Prc_P_PurchaseRfqAfterSave` |
|
||||
| Form varsayılanları | SupplierResponse=Waiting |
|
||||
|
||||
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `SupplierResponse` | Tedarikçi Yanıtı | dxSelectBox | ✓ | ✓ | liste: Waiting, Quoted, NotQuoted |
|
||||
| `QuoteDate` | Teklif Tarihi | dxDateBox | | ✓ | |
|
||||
| `QuoteValidUntil` | Teklif Geçerliliği | dxDateBox | | ✓ | |
|
||||
|
||||
#### Teklif Diğer Bilgiler — `App.Prc.PurchaseRfqOther`
|
||||
|
||||
| Özellik | Değer |
|
||||
| --- | --- |
|
||||
| Wizard | `wizard/Prc_PurchaseRfqOther.json` |
|
||||
| Yol | Liste (Wizard) |
|
||||
| Menü | Menüsüz (alt form) |
|
||||
| Yetki | `App.Prc.PurchaseRfqOther` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||
| Açıklama | Teklif Diğer Bilgiler — teklif talebinin alıcı, proje, ticari koşulları ve kıyas ağırlıkları. |
|
||||
| Geliştirme talebi | Satınalma -> Siparişler |
|
||||
| Kaynak | `Prc_T_PurchaseRfq` · filtre `"IsDeleted" = 'false'` |
|
||||
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||
| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup |
|
||||
| Kapsam | Kiracı |
|
||||
| Komutlar | UpdateBefore: SQL · UpdateAfter: `Prc_P_PurchaseRfqAfterSave` |
|
||||
|
||||
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `BuyerUserId` | Alıcı | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers |
|
||||
| `PaymentTermId` | Ödeme Süresi | dxSelectBox | | ✓ | sorgu: Prc_T_PaymentTerm |
|
||||
| `ProjectId` | Proje | dxSelectBox | | ✓ | sorgu: Prj_T_Project |
|
||||
| `IncotermId` | Teslimat Koşulu | dxSelectBox | | ✓ | sorgu: Prc_T_Incoterm |
|
||||
| `IncotermLocation` | Incoterm Konumu | dxTextBox | | ✓ | |
|
||||
| `PriceWeight` | Fiyat Ağırlığı (%) | dxNumberBox | ✓ | ✓ | |
|
||||
| `DeliveryWeight` | Termin Ağırlığı (%) | dxNumberBox | ✓ | ✓ | |
|
||||
|
||||
#### İhale Teklifleri — `App.Prc.PurchaseRfqAlternative`
|
||||
|
||||
| Özellik | Değer |
|
||||
| --- | --- |
|
||||
| Wizard | `wizard/Prc_PurchaseRfqAlternative.json` |
|
||||
| Yol | Liste (Wizard) |
|
||||
| Menü | Menüsüz (alt form) |
|
||||
| Yetki | `App.Prc.PurchaseRfqAlternative` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||
| Açıklama | İhale Teklifleri — aynı ihalenin diğer teklif talepleri; alternatifler burada oluşturulur. |
|
||||
| Geliştirme talebi | Satınalma -> Siparişler |
|
||||
| Kaynak | `Prc_V_PurchaseRfqAlternative` · filtre `"IsDeleted" = 'false'` |
|
||||
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||
| Düzenleme | ekle ✓ · düzenle ✗ · sil ✗ · popup |
|
||||
| Kapsam | Kiracı |
|
||||
|
||||
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `BaseId` | Ana Belge | dxTextBox | | | |
|
||||
| `RfqNo` | Teklif Talep No | dxTextBox | | | |
|
||||
| `SupplierId` | Tedarikçi | dxSelectBox | ✓ | ✓ | sorgu: Adm_T_Contact |
|
||||
| `Status` | Durum | dxSelectBox | | | liste: Draft, Sent, Purchase, Cancelled |
|
||||
| `SupplierResponse` | Tedarikçi Yanıtı | dxSelectBox | | | liste: Waiting, Quoted, NotQuoted |
|
||||
| `OrderDeadline` | Sipariş Zaman Sınırı | dxDateBox | | | |
|
||||
| `ExpectedArrival` | Beklenen Geliş | dxDateBox | | | |
|
||||
| `UntaxedAmount` | Vergi Hariç Tutar | dxNumberBox | | | |
|
||||
| `TotalAmount` | Toplam Tutar | dxNumberBox | | | |
|
||||
| `CurrencyId` | Para Birimi | dxTextBox | | | |
|
||||
|
||||
#### Fiyat Karşılaştırması — `App.Prc.PurchaseRfqComparison`
|
||||
|
||||
| Özellik | Değer |
|
||||
| --- | --- |
|
||||
| Wizard | `wizard/Prc_PurchaseRfqComparison.json` |
|
||||
| Yol | Liste (Wizard) |
|
||||
| Menü | Menüsüz (alt form) |
|
||||
| Yetki | `App.Prc.PurchaseRfqComparison` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||
| Açıklama | Fiyat Karşılaştırması — ihalenin her kalemi tedarikçi bazında yan yana, fiyat ve termine göre puanlanmış. |
|
||||
| Geliştirme talebi | Satınalma -> Siparişler |
|
||||
| Kaynak | `Prc_V_PurchaseRfqComparison` · filtre `"IsDeleted" = 'false'` |
|
||||
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||
| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · batch |
|
||||
| Kapsam | Kiracı |
|
||||
| Komutlar | UpdateBefore: SQL · UpdateAfter: `Prc_P_PurchaseRfqRecalc` |
|
||||
|
||||
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `BaseId` | Ana Belge | dxTextBox | | | |
|
||||
| `ProductId` | Ürün | dxSelectBox | | | sorgu: Inv_T_Product |
|
||||
| `RfqNo` | Teklif Talep No | dxTextBox | | | |
|
||||
| `SupplierId` | Tedarikçi | dxSelectBox | | | sorgu: Adm_T_Contact |
|
||||
| `Status` | Durum | dxSelectBox | | | liste: Draft, Sent, Purchase, Cancelled |
|
||||
| `Quantity` | Miktar | dxNumberBox | | | |
|
||||
| `UomId` | Birim | dxSelectBox | | | sorgu: Adm_T_Uom |
|
||||
| `UnitPrice` | Birim Fiyat | dxNumberBox | ✓ | ✓ | |
|
||||
| `CurrencyId` | Para Birimi | dxTextBox | | | |
|
||||
| `PriceTry` | Fiyat (TL) | dxNumberBox | | | |
|
||||
| `DeliveryDate` | Teslim Tarihi | dxDateBox | | ✓ | |
|
||||
| `LeadDays` | Termin (Gün) | dxNumberBox | | | |
|
||||
| `Score` | Puan | dxNumberBox | | | |
|
||||
| `IsRecommended` | Önerilen | dxCheckBox | | | |
|
||||
| `IsSelected` | Seçili | dxCheckBox | | ✓ | |
|
||||
|
||||
#### Sipariş Kalemleri — `App.Prc.PurchaseOrderLine`
|
||||
|
||||
| Özellik | Değer |
|
||||
|
|
@ -693,7 +874,7 @@ Yönetim › Tanımlamalar › Kontaklar (tedarikçi, e-posta, Satınalma sekmes
|
|||
| Yol | Liste (Wizard) |
|
||||
| Menü | Menüsüz (alt form) |
|
||||
| Yetki | `App.Prc.PurchaseOrderLine` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||
| Açıklama | Sipariş Kalemleri — teklif talebinin ya da satınalma siparişinin ürünleri. |
|
||||
| Açıklama | Sipariş Kalemleri — satınalma siparişinin ürünleri. |
|
||||
| Geliştirme talebi | Satınalma -> Siparişler |
|
||||
| Kaynak | `Prc_T_PurchaseOrderLine` · filtre `"IsDeleted" = 'false'` |
|
||||
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||
|
|
@ -710,33 +891,37 @@ Yönetim › Tanımlamalar › Kontaklar (tedarikçi, e-posta, Satınalma sekmes
|
|||
| `Quantity` | Miktar | dxNumberBox | ✓ | ✓ | |
|
||||
| `UomId` | Birim | dxSelectBox | ✓ | ✓ | sorgu: Adm_T_Uom |
|
||||
| `UnitPrice` | Birim Fiyat | dxNumberBox | ✓ | ✓ | |
|
||||
| `TaxRate` | Vergiler (%) | dxNumberBox | ✓ | ✓ | |
|
||||
| `TaxRate` | Vergi Oran | dxNumberBox | ✓ | ✓ | |
|
||||
| `Amount` | Tutar | dxNumberBox | | ✓ | script |
|
||||
| `DeliveryDate` | Teslim Tarihi | dxDateBox | | ✓ | |
|
||||
| `MaterialRequestItemId` | Talep | dxSelectBox | | ✓ | sorgu: Prc_T_MaterialRequestItem |
|
||||
|
||||
#### Tedarikçi Teklifi — `App.Prc.PurchaseOrderQuote`
|
||||
#### Sipariş Talep Kalemleri — `App.Prc.PurchaseOrderImportItem`
|
||||
|
||||
| Özellik | Değer |
|
||||
| --- | --- |
|
||||
| Wizard | `wizard/Prc_PurchaseOrderQuote.json` |
|
||||
| Wizard | `wizard/Prc_PurchaseOrderImportItem.json` |
|
||||
| Yol | Liste (Wizard) |
|
||||
| Menü | Menüsüz (alt form) |
|
||||
| Yetki | `App.Prc.PurchaseOrderQuote` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||
| Açıklama | Tedarikçi Teklifi — tedarikçinin teklif talebine verdiği yanıt. |
|
||||
| Yetki | `App.Prc.PurchaseOrderImportItem` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||
| Açıklama | Sipariş Talep Kalemleri — onaylı malzeme taleplerinin henüz hiçbir teklifte ya da siparişte olmayan kalemleri, teklifsiz yazılan taslak sipariş için listelenir. |
|
||||
| Geliştirme talebi | Satınalma -> Siparişler |
|
||||
| Kaynak | `Prc_T_PurchaseOrder` · filtre `"IsDeleted" = 'false'` |
|
||||
| Kaynak | `Prc_V_PurchaseImportItem` |
|
||||
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||
| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup |
|
||||
| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · batch |
|
||||
| Kapsam | Kiracı |
|
||||
| Komutlar | UpdateAfter: SQL |
|
||||
| Form varsayılanları | SupplierResponse=Waiting |
|
||||
|
||||
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `SupplierResponse` | Tedarikçi Yanıtı | dxSelectBox | ✓ | ✓ | liste: Waiting, Quoted, NotQuoted |
|
||||
| `QuoteValidUntil` | Teklif Geçerliliği | dxDateBox | | ✓ | |
|
||||
| `QuoteDate` | Teklif Tarihi | dxDateBox | | ✓ | |
|
||||
| `QuotedByUserId` | Teklifi Veren | dxSelectBox | | ✓ | sorgu: AbpUsers |
|
||||
| `BaseId` | Ana Belge | dxTextBox | | | |
|
||||
| `RequestNo` | Talep No | dxTextBox | | | |
|
||||
| `RequesterUserId` | Talep Eden | dxSelectBox | | | sorgu: AbpUsers |
|
||||
| `ProductId` | Ürün | dxSelectBox | | | sorgu: Inv_T_Product |
|
||||
| `Quantity` | Miktar | dxNumberBox | | | |
|
||||
| `UomId` | Birim | dxSelectBox | | | sorgu: Adm_T_Uom |
|
||||
| `DueDate` | Bitiş Tarihi | dxDateBox | | | |
|
||||
| `RequestReason` | Talep Nedeni | dxTextBox | | | |
|
||||
| `Transfer` | Aktar | dxCheckBox | | ✓ | |
|
||||
|
||||
#### Diğer Bilgiler — `App.Prc.PurchaseOrderOther`
|
||||
|
||||
|
|
@ -746,23 +931,23 @@ Yönetim › Tanımlamalar › Kontaklar (tedarikçi, e-posta, Satınalma sekmes
|
|||
| Yol | Liste (Wizard) |
|
||||
| Menü | Menüsüz (alt form) |
|
||||
| Yetki | `App.Prc.PurchaseOrderOther` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||
| Açıklama | Diğer Bilgiler — teklif talebinin ya da satınalma siparişinin alıcı, kaynak, proje ve ticari koşulları. |
|
||||
| Açıklama | Diğer Bilgiler — satınalma siparişinin alıcı, proje ve ticari koşulları. |
|
||||
| Geliştirme talebi | Satınalma -> Siparişler |
|
||||
| Kaynak | `Prc_T_PurchaseOrder` · filtre `"IsDeleted" = 'false'` |
|
||||
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||
| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup |
|
||||
| Kapsam | Kiracı |
|
||||
| Komutlar | UpdateBefore: SQL |
|
||||
|
||||
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `BuyerUserId` | Alıcı | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers |
|
||||
| `PaymentTermId` | Ödeme Koşulları | dxSelectBox | | ✓ | sorgu: Prc_T_PaymentTerm |
|
||||
| `SourceDocument` | Kaynak | dxTextBox | | ✓ | |
|
||||
| `PaymentTermId` | Ödeme Süresi | dxSelectBox | | ✓ | sorgu: Prc_T_PaymentTerm |
|
||||
| `ProjectId` | Proje | dxSelectBox | | ✓ | sorgu: Prj_T_Project |
|
||||
| `IncotermId` | Teslimat Koşulu | dxSelectBox | | ✓ | sorgu: Prc_T_Incoterm |
|
||||
| `IncotermLocation` | Incoterm Konumu | dxTextBox | | ✓ | |
|
||||
|
||||
#### Teklifler — `App.Prc.PurchaseOrderAlternative`
|
||||
#### Kaynak Teklifler — `App.Prc.PurchaseOrderAlternative`
|
||||
|
||||
| Özellik | Değer |
|
||||
| --- | --- |
|
||||
|
|
@ -770,23 +955,24 @@ Yönetim › Tanımlamalar › Kontaklar (tedarikçi, e-posta, Satınalma sekmes
|
|||
| Yol | Liste (Wizard) |
|
||||
| Menü | Menüsüz (alt form) |
|
||||
| Yetki | `App.Prc.PurchaseOrderAlternative` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||
| Açıklama | Teklifler — açık belgeyle aynı malzeme talebinin kalemlerini taşıyan diğer teklif talepleri ve siparişler. |
|
||||
| Açıklama | Kaynak Teklifler — satınalma siparişinin dönüştürüldüğü ihalenin teklif talepleri. |
|
||||
| Geliştirme talebi | Satınalma -> Siparişler |
|
||||
| Kaynak | `Prc_V_PurchaseOrderAlternative` |
|
||||
| Kaynak | `Prc_V_PurchaseRfqAlternative` · filtre `"IsDeleted" = 'false'` |
|
||||
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||
| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup |
|
||||
| Kapsam | Kiracı |
|
||||
|
||||
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `BaseOrderId` | Ana Belge | dxTextBox | | | |
|
||||
| `OrderNo` | Referans | dxTextBox | | | |
|
||||
| `BaseId` | Ana Belge | dxTextBox | | | |
|
||||
| `RfqNo` | Teklif Talep No | dxTextBox | | | |
|
||||
| `SupplierId` | Tedarikçi | dxSelectBox | | | sorgu: Adm_T_Contact |
|
||||
| `Status` | Durum | dxSelectBox | | | liste: Draft, Sent, Purchase, Cancelled |
|
||||
| `SupplierResponse` | Tedarikçi Yanıtı | dxSelectBox | | | liste: Waiting, Quoted, NotQuoted |
|
||||
| `OrderDeadline` | Sipariş Zaman Sınırı | dxDateBox | | | |
|
||||
| `ExpectedArrival` | Beklenen Geliş | dxDateBox | | | |
|
||||
| `TotalAmount` | Toplam | dxNumberBox | | | |
|
||||
| `UntaxedAmount` | Vergi Hariç Tutar | dxNumberBox | | | |
|
||||
| `TotalAmount` | Toplam Tutar | dxNumberBox | | | |
|
||||
| `CurrencyId` | Para Birimi | dxTextBox | | | |
|
||||
| `Status` | Durumu | dxSelectBox | | | liste: Draft, Sent, Purchase, Cancelled |
|
||||
|
||||
<!-- module-doc:auto:end -->
|
||||
|
|
|
|||
41
configs/seeds/postgres/object/Adm_P_SequenceNext.sql
Normal file
41
configs/seeds/postgres/object/Adm_P_SequenceNext.sql
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
-- SQL tarafında açılan belgenin (yordamın ürettiği teklif, sipariş) numarasını numaratörden alır.
|
||||
-- Biçim ve sıfırlama kuralı Sequence.GetNextSequence ile birebir aynıdır; biri değişirse diğeri de değişir.
|
||||
CREATE OR REPLACE PROCEDURE public."Adm_P_SequenceNext"(p_name varchar, p_tenant_id uuid, INOUT p_value varchar DEFAULT NULL)
|
||||
LANGUAGE plpgsql AS $$
|
||||
DECLARE v_id uuid; v_reset int; v_period varchar(16); v_number bigint; v_step int; v_padding int;
|
||||
v_prefix varchar(64); v_suffix varchar(64); v_template varchar(256); v_text varchar(32); v_now timestamp := LOCALTIMESTAMP;
|
||||
BEGIN
|
||||
SELECT "Id", "ResetPeriod" INTO v_id, v_reset
|
||||
FROM "Adm_T_Sequence"
|
||||
WHERE "Name" = p_name AND "IsActive" = true AND "IsDeleted" = false AND "TenantId" IS NOT DISTINCT FROM p_tenant_id
|
||||
LIMIT 1
|
||||
FOR UPDATE;
|
||||
IF v_id IS NULL THEN
|
||||
RAISE EXCEPTION 'Numaratör bulunamadı: %', p_name USING ERRCODE = 'P0001', DETAIL = '50190';
|
||||
END IF;
|
||||
|
||||
v_period := CASE v_reset WHEN 1 THEN to_char(v_now, 'YYYY') WHEN 2 THEN to_char(v_now, 'YYYYMM') WHEN 3 THEN to_char(v_now, 'YYYYMMDD')
|
||||
WHEN 4 THEN to_char(v_now, 'YYYYMMDDHH24') WHEN 5 THEN to_char(v_now, 'YYYYMMDDHH24MI') END;
|
||||
|
||||
SELECT CASE WHEN v_period IS NOT NULL AND COALESCE("LastPeriodKey", '') <> v_period THEN "StartNumber" ELSE "NextNumber" END,
|
||||
"IncrementStep", "PaddingSize", COALESCE("Prefix", ''), COALESCE("Suffix", ''),
|
||||
CASE WHEN TRIM(COALESCE("FormatTemplate", '')) = '' THEN '{Prefix}{Number}{Suffix}' ELSE "FormatTemplate" END
|
||||
INTO v_number, v_step, v_padding, v_prefix, v_suffix, v_template
|
||||
FROM "Adm_T_Sequence" WHERE "Id" = v_id;
|
||||
|
||||
UPDATE "Adm_T_Sequence"
|
||||
SET "NextNumber" = v_number + v_step, "LastPeriodKey" = COALESCE(v_period, "LastPeriodKey")
|
||||
WHERE "Id" = v_id;
|
||||
|
||||
v_text := v_number::text;
|
||||
IF length(v_text) < v_padding THEN v_text := lpad(v_text, v_padding, '0'); END IF;
|
||||
|
||||
p_value := replace(replace(replace(v_template, '{Prefix}', v_prefix), '{Suffix}', v_suffix), '{Number}', v_text);
|
||||
p_value := replace(replace(p_value, '{yyyy}', to_char(v_now, 'YYYY')), '{yy}', to_char(v_now, 'YY'));
|
||||
p_value := replace(replace(p_value, '{MM}', to_char(v_now, 'MM')), '{M}', to_char(v_now, 'FMMM'));
|
||||
p_value := replace(replace(p_value, '{dd}', to_char(v_now, 'DD')), '{d}', to_char(v_now, 'FMDD'));
|
||||
p_value := replace(replace(p_value, '{HH}', to_char(v_now, 'HH24')), '{H}', to_char(v_now, 'FMHH24'));
|
||||
p_value := replace(replace(p_value, '{mm}', to_char(v_now, 'MI')), '{m}', to_char(v_now, 'FMMI'));
|
||||
p_value := replace(replace(p_value, '{ss}', to_char(v_now, 'SS')), '{s}', to_char(v_now, 'FMSS'));
|
||||
END;
|
||||
$$;
|
||||
52
configs/seeds/postgres/object/Prc_P_PurchaseImportItem.sql
Normal file
52
configs/seeds/postgres/object/Prc_P_PurchaseImportItem.sql
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
-- Talep Kalemleri sekmesinde işaretlenen kalemi (p_key = belge|kalem) teklif talebine ya da taslak siparişe kopyalar.
|
||||
-- Fiyat: sözleşme kalemi › tedarikçi fiyatı › 0; termin talebin istenen tarihidir.
|
||||
CREATE OR REPLACE PROCEDURE public."Prc_P_PurchaseImportItem"(p_key varchar, p_transfer boolean DEFAULT true)
|
||||
LANGUAGE plpgsql AS $$
|
||||
DECLARE v_doc uuid; v_item uuid; v_is_order boolean := false; v_tenant uuid; v_supplier uuid; v_agr uuid; v_status varchar(16);
|
||||
v_product uuid; v_description varchar(512); v_quantity numeric(18, 4); v_uom varchar(50); v_price numeric(18, 4);
|
||||
v_tax numeric(18, 4); v_due timestamp;
|
||||
BEGIN
|
||||
IF NOT COALESCE(p_transfer, false) THEN RETURN; END IF;
|
||||
IF p_key !~* '^[0-9a-f-]{36}\|[0-9a-f-]{36}$' THEN
|
||||
RAISE EXCEPTION 'Talep kalemi yalnız teklif aşamasındaki teklif talebine ya da taslak siparişe aktarılabilir.' USING ERRCODE = 'P0001', DETAIL = '50161';
|
||||
END IF;
|
||||
v_doc := left(p_key, 36)::uuid;
|
||||
v_item := right(p_key, 36)::uuid;
|
||||
|
||||
SELECT "TenantId", "SupplierId", "AgreementId", "Status" INTO v_tenant, v_supplier, v_agr, v_status
|
||||
FROM "Prc_T_PurchaseRfq" WHERE "Id" = v_doc AND "IsDeleted" = false AND "Status" IN ('Draft', 'Sent');
|
||||
IF v_status IS NULL THEN
|
||||
SELECT "TenantId", "SupplierId", "AgreementId", "Status", true INTO v_tenant, v_supplier, v_agr, v_status, v_is_order
|
||||
FROM "Prc_T_PurchaseOrder" WHERE "Id" = v_doc AND "IsDeleted" = false AND "Status" = 'Draft';
|
||||
END IF;
|
||||
IF v_status IS NULL THEN
|
||||
RAISE EXCEPTION 'Talep kalemi yalnız teklif aşamasındaki teklif talebine ya da taslak siparişe aktarılabilir.' USING ERRCODE = 'P0001', DETAIL = '50161';
|
||||
END IF;
|
||||
|
||||
SELECT a."ProductId", a."RequestReason", a."Quantity", a."UomId", a."DueDate", COALESCE(p."PurchaseTaxRate", 0),
|
||||
COALESCE((SELECT al."UnitPrice" FROM "Prc_T_PurchaseAgreementLine" al
|
||||
WHERE al."AgreementId" = v_agr AND al."ProductId" = a."ProductId" AND al."IsDeleted" = false LIMIT 1),
|
||||
(SELECT ps."Price" FROM "Inv_T_ProductSupplier" ps
|
||||
WHERE ps."ProductId" = a."ProductId" AND ps."ContactId" = v_supplier AND ps."IsDeleted" = false
|
||||
ORDER BY ps."MinQuantity" LIMIT 1), 0)
|
||||
INTO v_product, v_description, v_quantity, v_uom, v_due, v_tax, v_price
|
||||
FROM "Prc_V_MaterialRequestAvailableItem" a
|
||||
LEFT JOIN "Inv_T_Product" p ON p."Id" = a."ProductId"
|
||||
WHERE a."Id" = v_item AND a."TenantId" IS NOT DISTINCT FROM v_tenant;
|
||||
IF v_product IS NULL THEN
|
||||
RAISE EXCEPTION 'Talep kalemi artık aktarılamaz: başka bir teklife ya da siparişe aktarılmış veya talep değişmiş.' USING ERRCODE = 'P0001', DETAIL = '50162';
|
||||
END IF;
|
||||
|
||||
IF v_is_order THEN
|
||||
INSERT INTO "Prc_T_PurchaseOrderLine" ("Id", "TenantId", "PurchaseOrderId", "ProductId", "Description", "Quantity", "UomId",
|
||||
"UnitPrice", "TaxRate", "Amount", "DeliveryDate", "MaterialRequestItemId", "CreationTime", "IsDeleted")
|
||||
VALUES (gen_random_uuid(), v_tenant, v_doc, v_product, v_description, v_quantity, v_uom, v_price, v_tax, 0, v_due, v_item, NOW() AT TIME ZONE 'UTC', false);
|
||||
CALL public."Prc_P_PurchaseOrderRecalc"(v_doc);
|
||||
ELSE
|
||||
INSERT INTO "Prc_T_PurchaseRfqLine" ("Id", "TenantId", "PurchaseRfqId", "ProductId", "Description", "Quantity", "UomId",
|
||||
"UnitPrice", "TaxRate", "Amount", "DeliveryDate", "MaterialRequestItemId", "CreationTime", "IsDeleted")
|
||||
VALUES (gen_random_uuid(), v_tenant, v_doc, v_product, v_description, v_quantity, v_uom, v_price, v_tax, 0, v_due, v_item, NOW() AT TIME ZONE 'UTC', false);
|
||||
CALL public."Prc_P_PurchaseRfqRecalc"(v_doc);
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
CREATE OR REPLACE PROCEDURE public."Prc_P_PurchaseOrderAfterSave"(p_id uuid, p_user_id uuid DEFAULT NULL)
|
||||
LANGUAGE plpgsql AS $$
|
||||
DECLARE v_req uuid; v_act varchar(16); v_agr uuid;
|
||||
DECLARE v_act varchar(16);
|
||||
BEGIN
|
||||
SELECT "PendingAction" INTO v_act FROM "Prc_T_PurchaseOrder" WHERE "Id" = p_id;
|
||||
UPDATE "Prc_T_PurchaseOrder" o SET
|
||||
"PaymentTermId" = COALESCE(o."PaymentTermId", c."PurchasePaymentTermId"),
|
||||
"IncotermId" = COALESCE(o."IncotermId", c."PurchaseIncotermId"),
|
||||
|
|
@ -10,11 +11,8 @@ BEGIN
|
|||
FROM "Adm_T_Contact" c
|
||||
WHERE o."Id" = p_id AND c."Id" = o."SupplierId";
|
||||
|
||||
SELECT "MaterialRequestId", "PendingAction", "AgreementId" INTO v_req, v_act, v_agr
|
||||
FROM "Prc_T_PurchaseOrder" WHERE "Id" = p_id;
|
||||
IF v_agr IS NOT NULL THEN CALL public."Prc_P_PurchaseRfqFromAgreement"(p_id); END IF;
|
||||
IF v_req IS NOT NULL THEN CALL public."Prc_P_PurchaseOrderImportRequest"(p_id); END IF;
|
||||
CALL public."Prc_P_PurchaseOrderRecalc"(p_id);
|
||||
-- Durum butonlari islemi PendingAction alanina yazip ekranin guncelleme ucuyla kaydeder.
|
||||
IF v_act IS NOT NULL THEN CALL public."Prc_P_PurchaseOrderSetStatus"(p_id, v_act, p_user_id); END IF;
|
||||
END;
|
||||
$$;
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
CREATE OR REPLACE PROCEDURE public."Prc_P_PurchaseOrderImportRequest"(p_id uuid)
|
||||
LANGUAGE plpgsql AS $$
|
||||
DECLARE v_req uuid; v_tenant uuid; v_supplier uuid; v_agr uuid; v_status varchar(16); v_cnt int;
|
||||
BEGIN
|
||||
SELECT "MaterialRequestId", "TenantId", "SupplierId", "AgreementId", "Status"
|
||||
INTO v_req, v_tenant, v_supplier, v_agr, v_status
|
||||
FROM "Prc_T_PurchaseOrder" WHERE "Id" = p_id;
|
||||
IF v_req IS NULL THEN RETURN; END IF;
|
||||
IF v_status = 'Cancelled' THEN
|
||||
RAISE EXCEPTION 'İptal edilmiş belgeye talepten aktarım yapılamaz.';
|
||||
END IF;
|
||||
|
||||
INSERT INTO "Prc_T_PurchaseOrderLine" ("Id", "TenantId", "PurchaseOrderId", "ProductId", "Description", "Quantity", "UomId",
|
||||
"UnitPrice", "TaxRate", "Amount", "MaterialRequestItemId", "CreationTime", "IsDeleted")
|
||||
SELECT gen_random_uuid(), v_tenant, p_id, i."ProductId", i."RequestReason", i."Quantity", i."UomId",
|
||||
COALESCE((SELECT al."UnitPrice" FROM "Prc_T_PurchaseAgreementLine" al
|
||||
WHERE al."AgreementId" = v_agr AND al."ProductId" = i."ProductId" AND al."IsDeleted" = false LIMIT 1),
|
||||
(SELECT ps."Price" FROM "Inv_T_ProductSupplier" ps
|
||||
WHERE ps."ProductId" = i."ProductId" AND ps."ContactId" = v_supplier AND ps."IsDeleted" = false
|
||||
ORDER BY ps."MinQuantity" LIMIT 1), 0),
|
||||
COALESCE(p."PurchaseTaxRate", 0), 0, i."Id", CURRENT_TIMESTAMP, false
|
||||
FROM "Prc_T_MaterialRequestItem" i
|
||||
INNER JOIN "Prc_T_MaterialRequest" r ON r."Id" = i."MaterialRequestId"
|
||||
LEFT JOIN "Inv_T_Product" p ON p."Id" = i."ProductId"
|
||||
WHERE i."MaterialRequestId" = v_req AND i."IsDeleted" = false
|
||||
AND r."ApprovalStatus" = 'Onaylandı'
|
||||
AND i."FulfillmentMethod" = 'Purchase' AND i."LineStatus" = 'Waiting'
|
||||
AND NOT EXISTS (SELECT 1 FROM "Prc_T_PurchaseOrderLine" ol
|
||||
INNER JOIN "Prc_T_PurchaseOrder" o ON o."Id" = ol."PurchaseOrderId"
|
||||
WHERE ol."MaterialRequestItemId" = i."Id" AND ol."IsDeleted" = false
|
||||
AND o."IsDeleted" = false AND o."Status" <> 'Cancelled');
|
||||
GET DIAGNOSTICS v_cnt = ROW_COUNT;
|
||||
|
||||
UPDATE "Prc_T_PurchaseOrder" SET "MaterialRequestId" = NULL WHERE "Id" = p_id;
|
||||
|
||||
IF v_cnt = 0 THEN
|
||||
RAISE EXCEPTION 'Seçilen talepte aktarılacak kalem yok (onaylı, Satınalma ile karşılanacak, bekleyen ve başka belgede olmayan kalem bulunamadı).';
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
|
|
@ -4,15 +4,16 @@ BEGIN
|
|||
UPDATE "Prc_T_PurchaseOrderLine" SET "Amount" = ROUND("Quantity" * "UnitPrice", 2)
|
||||
WHERE "PurchaseOrderId" = p_id AND "IsDeleted" = false;
|
||||
|
||||
-- Kaynak: teklif talebinden gelen siparişte teklif no, doğrudan yazılan siparişte talep numaraları.
|
||||
UPDATE "Prc_T_PurchaseOrder" o SET
|
||||
"UntaxedAmount" = COALESCE((SELECT SUM(l."Amount") FROM "Prc_T_PurchaseOrderLine" l WHERE l."PurchaseOrderId" = p_id AND l."IsDeleted" = false), 0),
|
||||
"TaxAmount" = COALESCE((SELECT SUM(ROUND(l."Amount" * l."TaxRate" / 100, 2)) FROM "Prc_T_PurchaseOrderLine" l WHERE l."PurchaseOrderId" = p_id AND l."IsDeleted" = false), 0),
|
||||
"SourceDocument" = (SELECT string_agg(s."RequestNo", ', ' ORDER BY s."RequestNo")
|
||||
FROM (SELECT DISTINCT r."RequestNo"
|
||||
FROM "Prc_T_PurchaseOrderLine" l
|
||||
INNER JOIN "Prc_T_MaterialRequestItem" i ON i."Id" = l."MaterialRequestItemId"
|
||||
INNER JOIN "Prc_T_MaterialRequest" r ON r."Id" = i."MaterialRequestId"
|
||||
WHERE l."PurchaseOrderId" = p_id AND l."IsDeleted" = false) s)
|
||||
"UntaxedAmount" = COALESCE((SELECT SUM(l."Amount") FROM "Prc_T_PurchaseOrderLine" l WHERE l."PurchaseOrderId" = p_id AND l."IsDeleted" = false), 0),
|
||||
"TaxAmount" = COALESCE((SELECT SUM(ROUND(l."Amount" * l."TaxRate" / 100, 2)) FROM "Prc_T_PurchaseOrderLine" l WHERE l."PurchaseOrderId" = p_id AND l."IsDeleted" = false), 0),
|
||||
"SourceDocument" = COALESCE((SELECT q."RfqNo" FROM "Prc_T_PurchaseRfq" q WHERE q."Id" = o."PurchaseRfqId"),
|
||||
(SELECT string_agg(DISTINCT m."RequestNo", ', ')
|
||||
FROM "Prc_T_PurchaseOrderLine" l
|
||||
INNER JOIN "Prc_T_MaterialRequestItem" i ON i."Id" = l."MaterialRequestItemId"
|
||||
INNER JOIN "Prc_T_MaterialRequest" m ON m."Id" = i."MaterialRequestId"
|
||||
WHERE l."PurchaseOrderId" = p_id AND l."IsDeleted" = false))
|
||||
WHERE o."Id" = p_id;
|
||||
|
||||
UPDATE "Prc_T_PurchaseOrder" SET "TotalAmount" = "UntaxedAmount" + "TaxAmount" WHERE "Id" = p_id;
|
||||
|
|
|
|||
|
|
@ -1,45 +1,45 @@
|
|||
CREATE OR REPLACE PROCEDURE public."Prc_P_PurchaseOrderSend"(p_id uuid, p_user_id uuid DEFAULT NULL)
|
||||
LANGUAGE plpgsql AS $$
|
||||
DECLARE v_tenant uuid; v_no varchar(32); v_status varchar(16); v_email varchar(256); v_supplier varchar(256);
|
||||
v_type_name varchar(64); v_type uuid; v_subject varchar(256); v_lines text; v_total numeric; v_cur varchar(8);
|
||||
DECLARE v_tenant uuid; v_no varchar(32); v_email varchar(256); v_supplier varchar(256);
|
||||
v_subject varchar(256); v_lines text; v_total numeric; v_cur varchar(8);
|
||||
BEGIN
|
||||
SELECT o."TenantId", o."OrderNo", o."Status", c."Email", c."Name", o."TotalAmount", o."CurrencyId"
|
||||
INTO v_tenant, v_no, v_status, v_email, v_supplier, v_total, v_cur
|
||||
SELECT o."TenantId", o."OrderNo", c."Email", c."Name", o."TotalAmount", o."CurrencyId"
|
||||
INTO v_tenant, v_no, v_email, v_supplier, v_total, v_cur
|
||||
FROM "Prc_T_PurchaseOrder" o LEFT JOIN "Adm_T_Contact" c ON c."Id" = o."SupplierId"
|
||||
WHERE o."Id" = p_id;
|
||||
|
||||
IF NOT EXISTS (SELECT 1 FROM "Prc_T_PurchaseOrderLine" WHERE "PurchaseOrderId" = p_id AND "IsDeleted" = false) THEN
|
||||
RAISE EXCEPTION 'Kalemi olmayan belge gönderilemez.';
|
||||
RAISE EXCEPTION 'Kalemi olmayan sipariş gönderilemez.' USING ERRCODE = 'P0001', DETAIL = '50185';
|
||||
END IF;
|
||||
IF COALESCE(v_email, '') = '' THEN
|
||||
RAISE EXCEPTION 'Tedarikçinin kontak kartında e-posta adresi yok.';
|
||||
RAISE EXCEPTION 'Tedarikçinin kontak kartında e-posta adresi yok.' USING ERRCODE = 'P0001', DETAIL = '50186';
|
||||
END IF;
|
||||
|
||||
IF v_status = 'Purchase' THEN v_type_name := 'Prc.PurchaseOrderSent'; v_subject := 'Satınalma Siparişi ' || v_no;
|
||||
ELSE v_type_name := 'Prc.RfqSent'; v_subject := 'Teklif Talebi ' || v_no; END IF;
|
||||
v_subject := 'Satınalma Siparişi ' || v_no;
|
||||
|
||||
SELECT "Id" INTO v_type FROM "Adm_T_NotificationType"
|
||||
WHERE "Name" = v_type_name AND "IsDeleted" = false AND ("TenantId" = v_tenant OR ("TenantId" IS NULL AND v_tenant IS NULL)) LIMIT 1;
|
||||
|
||||
SELECT string_agg('<tr><td>' || COALESCE(p."Name", '') || '</td><td>' || COALESCE(l."Description", '') || '</td><td style="text-align:right">'
|
||||
|| TRIM(TO_CHAR(l."Quantity", 'FM999G999G990D##')) || ' ' || l."UomId" || '</td><td style="text-align:right">'
|
||||
|| TRIM(TO_CHAR(l."UnitPrice", 'FM999G999G990D00')) || '</td><td style="text-align:right">%'
|
||||
|| TRIM(TO_CHAR(l."TaxRate", 'FM990')) || '</td><td style="text-align:right">'
|
||||
|| TRIM(TO_CHAR(l."Amount", 'FM999G999G990D00')) || '</td></tr>', '' ORDER BY l."CreationTime")
|
||||
SELECT string_agg('<tr><td>' || COALESCE(p."Name", '') || '</td><td>' || COALESCE(l."Description", '') || '</td><td>'
|
||||
|| TRIM(TO_CHAR(l."Quantity", 'FM999G999G990D00')) || ' ' || l."UomId" || '</td><td>'
|
||||
|| TRIM(TO_CHAR(l."UnitPrice", 'FM999G999G990D00')) || '</td><td>%'
|
||||
|| TRIM(TO_CHAR(l."TaxRate", 'FM990')) || '</td><td>'
|
||||
|| TRIM(TO_CHAR(l."Amount", 'FM999G999G990D00')) || '</td><td>'
|
||||
|| COALESCE(TO_CHAR(l."DeliveryDate", 'DD.MM.YYYY'), '') || '</td></tr>', '' ORDER BY l."CreationTime")
|
||||
INTO v_lines
|
||||
FROM "Prc_T_PurchaseOrderLine" l LEFT JOIN "Inv_T_Product" p ON p."Id" = l."ProductId"
|
||||
WHERE l."PurchaseOrderId" = p_id AND l."IsDeleted" = false;
|
||||
|
||||
INSERT INTO "Adm_T_Notification" ("Id", "TenantId", "NotificationTypeId", "NotificationChannel", "Identifier", "Subject", "Message",
|
||||
-- Alıcı tedarikçinin e-postasıdır; tipin aktif Custom Mail kuralı gönderimi açar (kural kapatılırsa e-posta kuyruğa girmez).
|
||||
INSERT INTO "Adm_T_Notification" ("Id", "TenantId", "NotificationRuleId", "NotificationTypeId", "NotificationChannel", "Identifier", "Subject", "Message",
|
||||
"IsSent", "IsRead", "CreationTime", "CreatorId", "IsDeleted")
|
||||
VALUES (gen_random_uuid(), v_tenant, v_type, 'Mail', v_email, v_subject,
|
||||
SELECT gen_random_uuid(), v_tenant, r."Id", t."Id", r."Channel", v_email, v_subject, LEFT(
|
||||
'<p>Sayın ' || COALESCE(v_supplier, '') || ',</p><p>' || v_subject || ' aşağıda bilgilerinize sunulmuştur.</p>'
|
||||
|| '<table border="1" cellpadding="4" cellspacing="0"><tr><th>Ürün</th><th>Açıklama</th><th>Miktar</th><th>Birim Fiyat</th><th>KDV</th><th>Tutar</th></tr>'
|
||||
|| '<table border="1" cellpadding="4" cellspacing="0"><tr><th>Ürün</th><th>Açıklama</th><th>Miktar</th><th>Birim Fiyat</th><th>KDV</th><th>Tutar</th><th>Termin</th></tr>'
|
||||
|| COALESCE(v_lines, '') || '</table><p><b>Toplam: ' || TRIM(TO_CHAR(v_total, 'FM999G999G990D00')) || ' ' || v_cur || '</b></p>',
|
||||
false, false, CURRENT_TIMESTAMP, p_user_id, false);
|
||||
2048), false, false, NOW() AT TIME ZONE 'UTC', p_user_id, false
|
||||
FROM "Adm_T_NotificationType" t
|
||||
INNER JOIN "Adm_T_NotificationRule" r ON r."NotificationTypeId" = t."Id" AND r."IsActive" = true AND r."IsCustomized" = false AND r."IsDeleted" = false
|
||||
AND r."RecipientType" = 'Custom' AND r."RecipientId" IS NULL AND r."Channel" = 'Mail'
|
||||
WHERE t."Name" = 'SatinalmaSiparisiGonderildi' AND t."IsDeleted" = false AND t."TenantId" IS NOT DISTINCT FROM v_tenant;
|
||||
|
||||
UPDATE "Prc_T_PurchaseOrder" SET "LastSentDate" = CURRENT_TIMESTAMP,
|
||||
"Status" = CASE WHEN "Status" = 'Draft' THEN 'Sent' ELSE "Status" END
|
||||
WHERE "Id" = p_id;
|
||||
UPDATE "Prc_T_PurchaseOrder" SET "LastSentDate" = NOW() AT TIME ZONE 'UTC' WHERE "Id" = p_id;
|
||||
END;
|
||||
$$;
|
||||
|
|
|
|||
|
|
@ -5,19 +5,25 @@ BEGIN
|
|||
SELECT "Status" INTO v_status FROM "Prc_T_PurchaseOrder" WHERE "Id" = p_id;
|
||||
UPDATE "Prc_T_PurchaseOrder" SET "PendingAction" = NULL WHERE "Id" = p_id;
|
||||
|
||||
IF p_action = 'Send' THEN
|
||||
IF v_status = 'Cancelled' THEN RAISE EXCEPTION 'İptal edilmiş belge gönderilemez.'; END IF;
|
||||
CALL public."Prc_P_PurchaseOrderSend"(p_id, p_user_id);
|
||||
ELSIF p_action = 'Confirm' THEN
|
||||
IF v_status NOT IN ('Draft', 'Sent') THEN RAISE EXCEPTION 'Yalnız teklif aşamasındaki belge siparişe çevrilebilir.'; END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM "Prc_T_PurchaseOrderLine" WHERE "PurchaseOrderId" = p_id AND "IsDeleted" = false) THEN
|
||||
RAISE EXCEPTION 'Kalemi olmayan teklif onaylanamaz.';
|
||||
IF p_action = 'Confirm' THEN
|
||||
IF v_status <> 'Draft' THEN
|
||||
RAISE EXCEPTION 'Yalnız taslak sipariş onaylanabilir.' USING ERRCODE = 'P0001', DETAIL = '50181';
|
||||
END IF;
|
||||
UPDATE "Prc_T_PurchaseOrder" SET "Status" = 'Purchase', "ConfirmDate" = CURRENT_TIMESTAMP WHERE "Id" = p_id;
|
||||
IF NOT EXISTS (SELECT 1 FROM "Prc_T_PurchaseOrderLine" WHERE "PurchaseOrderId" = p_id AND "IsDeleted" = false) THEN
|
||||
RAISE EXCEPTION 'Kalemi olmayan sipariş onaylanamaz.' USING ERRCODE = 'P0001', DETAIL = '50182';
|
||||
END IF;
|
||||
UPDATE "Prc_T_PurchaseOrder" SET "Status" = 'Purchase', "ConfirmDate" = NOW() AT TIME ZONE 'UTC' WHERE "Id" = p_id;
|
||||
ELSIF p_action = 'Send' THEN
|
||||
IF v_status = 'Cancelled' THEN
|
||||
RAISE EXCEPTION 'İptal edilmiş sipariş gönderilemez.' USING ERRCODE = 'P0001', DETAIL = '50183';
|
||||
END IF;
|
||||
CALL public."Prc_P_PurchaseOrderSend"(p_id, p_user_id);
|
||||
ELSIF p_action = 'Cancel' THEN
|
||||
UPDATE "Prc_T_PurchaseOrder" SET "Status" = 'Cancelled' WHERE "Id" = p_id;
|
||||
ELSIF p_action = 'Draft' THEN
|
||||
IF v_status <> 'Cancelled' THEN RAISE EXCEPTION 'Yalnız iptal edilmiş belge taslağa alınabilir.'; END IF;
|
||||
IF v_status <> 'Cancelled' THEN
|
||||
RAISE EXCEPTION 'Yalnız iptal edilmiş sipariş taslağa alınabilir.' USING ERRCODE = 'P0001', DETAIL = '50184';
|
||||
END IF;
|
||||
UPDATE "Prc_T_PurchaseOrder" SET "Status" = 'Draft', "ConfirmDate" = NULL WHERE "Id" = p_id;
|
||||
END IF;
|
||||
END;
|
||||
|
|
|
|||
32
configs/seeds/postgres/object/Prc_P_PurchaseRfqAfterSave.sql
Normal file
32
configs/seeds/postgres/object/Prc_P_PurchaseRfqAfterSave.sql
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
CREATE OR REPLACE PROCEDURE public."Prc_P_PurchaseRfqAfterSave"(p_id uuid, p_user_id uuid DEFAULT NULL)
|
||||
LANGUAGE plpgsql AS $$
|
||||
DECLARE v_act varchar(16);
|
||||
BEGIN
|
||||
SELECT "PendingAction" INTO v_act FROM "Prc_T_PurchaseRfq" WHERE "Id" = p_id;
|
||||
IF EXISTS (SELECT 1 FROM "Prc_T_PurchaseRfq" WHERE "Id" = p_id AND "PriceWeight" + "DeliveryWeight" <> 100) THEN
|
||||
RAISE EXCEPTION 'Fiyat ve termin ağırlıklarının toplamı 100 olmalıdır.' USING ERRCODE = 'P0001', DETAIL = '50153';
|
||||
END IF;
|
||||
|
||||
-- İhalenin kökü ilk belgedir; alternatifler kökün Id'sini taşır.
|
||||
UPDATE "Prc_T_PurchaseRfq" r SET
|
||||
"TenderGroupId" = COALESCE(r."TenderGroupId", r."Id"),
|
||||
"QuoteDate" = CASE WHEN r."SupplierResponse" <> 'Waiting' THEN COALESCE(r."QuoteDate", NOW() AT TIME ZONE 'UTC') ELSE r."QuoteDate" END,
|
||||
"PaymentTermId" = COALESCE(r."PaymentTermId", c."PurchasePaymentTermId"),
|
||||
"IncotermId" = COALESCE(r."IncotermId", c."PurchaseIncotermId"),
|
||||
"IncotermLocation" = COALESCE(r."IncotermLocation", c."PurchaseIncotermLocation"),
|
||||
"BuyerUserId" = CASE WHEN r."LastModificationTime" IS NULL AND c."BuyerUserId" IS NOT NULL THEN c."BuyerUserId" ELSE r."BuyerUserId" END
|
||||
FROM "Adm_T_Contact" c
|
||||
WHERE r."Id" = p_id AND c."Id" = r."SupplierId";
|
||||
|
||||
-- Kıyas ağırlıkları ihale geneli tek değerdir; hangi belgede değişirse diğerlerine yazılır.
|
||||
UPDATE "Prc_T_PurchaseRfq" x SET "PriceWeight" = r."PriceWeight", "DeliveryWeight" = r."DeliveryWeight"
|
||||
FROM "Prc_T_PurchaseRfq" r
|
||||
WHERE r."Id" = p_id AND x."TenderGroupId" = r."TenderGroupId" AND x."Id" <> r."Id"
|
||||
AND (x."PriceWeight" <> r."PriceWeight" OR x."DeliveryWeight" <> r."DeliveryWeight");
|
||||
|
||||
CALL public."Prc_P_PurchaseRfqFromAgreement"(p_id);
|
||||
CALL public."Prc_P_PurchaseRfqRecalc"(p_id);
|
||||
-- Durum butonlari islemi PendingAction alanina yazip ekranin guncelleme ucuyla kaydeder.
|
||||
IF v_act IS NOT NULL THEN CALL public."Prc_P_PurchaseRfqSetStatus"(p_id, v_act, p_user_id); END IF;
|
||||
END;
|
||||
$$;
|
||||
58
configs/seeds/postgres/object/Prc_P_PurchaseRfqAward.sql
Normal file
58
configs/seeds/postgres/object/Prc_P_PurchaseRfqAward.sql
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
-- İhaleyi kalem bazında siparişe çevirir: kalemin Seçili satırı varsa o, yoksa Önerilen satır kazanır.
|
||||
-- Kazanan her teklif talebi için bir satınalma siparişi açılır (Kaynak = teklif no); kazanan teklif
|
||||
-- Satınalma Siparişi, hiç kalem kazanamayan teklif İptal Edildi olur.
|
||||
CREATE OR REPLACE PROCEDURE public."Prc_P_PurchaseRfqAward"(p_id uuid, p_user_id uuid DEFAULT NULL)
|
||||
LANGUAGE plpgsql AS $$
|
||||
DECLARE v_group uuid; v_tenant uuid; v_rfq uuid; v_po uuid; v_no varchar(128);
|
||||
BEGIN
|
||||
SELECT "TenderGroupId", "TenantId" INTO v_group, v_tenant FROM "Prc_T_PurchaseRfq" WHERE "Id" = p_id;
|
||||
IF EXISTS (SELECT 1 FROM "Prc_T_PurchaseRfq" WHERE "TenderGroupId" = v_group AND "IsDeleted" = false AND "Status" = 'Purchase') THEN
|
||||
RAISE EXCEPTION 'Bu ihale zaten siparişe dönüştürüldü.' USING ERRCODE = 'P0001', DETAIL = '50171';
|
||||
END IF;
|
||||
|
||||
DROP TABLE IF EXISTS pg_temp.prc_award_win;
|
||||
CREATE TEMP TABLE prc_award_win ON COMMIT DROP AS
|
||||
SELECT c."Id" AS line_id, c."PurchaseRfqId" AS rfq_id
|
||||
FROM "Prc_V_PurchaseRfqComparison" c
|
||||
WHERE c."BaseId" = p_id AND c."Status" <> 'Cancelled'
|
||||
AND (c."IsSelected"
|
||||
OR (c."IsRecommended" AND NOT EXISTS (SELECT 1 FROM "Prc_V_PurchaseRfqComparison" s
|
||||
WHERE s."BaseId" = p_id AND s."TenderLineId" = c."TenderLineId"
|
||||
AND s."IsSelected" AND s."Status" <> 'Cancelled')));
|
||||
IF NOT EXISTS (SELECT 1 FROM prc_award_win) THEN
|
||||
RAISE EXCEPTION 'Siparişe dönüştürülecek kalem yok: tedarikçi fiyat ve terminlerini girin ya da Fiyat Karşılaştırması sekmesinde kazananı seçin.'
|
||||
USING ERRCODE = 'P0001', DETAIL = '50172';
|
||||
END IF;
|
||||
|
||||
FOR v_rfq IN SELECT DISTINCT rfq_id FROM prc_award_win LOOP
|
||||
v_po := gen_random_uuid();
|
||||
CALL public."Adm_P_SequenceNext"('PurchaseOrder1', v_tenant, v_no);
|
||||
|
||||
INSERT INTO "Prc_T_PurchaseOrder" ("Id", "TenantId", "OrderNo", "PurchaseRfqId", "SupplierId", "SupplierReference", "AgreementId", "CurrencyId",
|
||||
"ExpectedArrival", "OperationTypeId", "ConfirmDate", "BuyerUserId", "ProjectId", "IncotermId", "IncotermLocation", "PaymentTermId", "Terms",
|
||||
"Status", "CreationTime", "CreatorId", "IsDeleted")
|
||||
SELECT v_po, "TenantId", v_no, "Id", "SupplierId", "SupplierReference", "AgreementId", "CurrencyId",
|
||||
"ExpectedArrival", "OperationTypeId", NOW() AT TIME ZONE 'UTC', "BuyerUserId", "ProjectId", "IncotermId", "IncotermLocation", "PaymentTermId", "Terms",
|
||||
'Purchase', NOW() AT TIME ZONE 'UTC', p_user_id, false
|
||||
FROM "Prc_T_PurchaseRfq" WHERE "Id" = v_rfq;
|
||||
|
||||
INSERT INTO "Prc_T_PurchaseOrderLine" ("Id", "TenantId", "PurchaseOrderId", "ProductId", "Description", "Quantity", "UomId", "UnitPrice", "TaxRate",
|
||||
"Amount", "DeliveryDate", "MaterialRequestItemId", "PurchaseRfqLineId", "CreationTime", "CreatorId", "IsDeleted")
|
||||
SELECT gen_random_uuid(), l."TenantId", v_po, l."ProductId", l."Description", l."Quantity", l."UomId", l."UnitPrice", l."TaxRate",
|
||||
0, l."DeliveryDate", l."MaterialRequestItemId", l."Id", NOW() AT TIME ZONE 'UTC', p_user_id, false
|
||||
FROM "Prc_T_PurchaseRfqLine" l
|
||||
INNER JOIN prc_award_win w ON w.line_id = l."Id"
|
||||
WHERE w.rfq_id = v_rfq;
|
||||
|
||||
CALL public."Prc_P_PurchaseOrderRecalc"(v_po);
|
||||
END LOOP;
|
||||
|
||||
UPDATE "Prc_T_PurchaseRfqLine" l SET "IsSelected" = EXISTS (SELECT 1 FROM prc_award_win w WHERE w.line_id = l."Id")
|
||||
FROM "Prc_T_PurchaseRfq" r
|
||||
WHERE r."Id" = l."PurchaseRfqId" AND r."TenderGroupId" = v_group AND r."IsDeleted" = false AND r."Status" <> 'Cancelled';
|
||||
|
||||
UPDATE "Prc_T_PurchaseRfq" r
|
||||
SET "Status" = CASE WHEN EXISTS (SELECT 1 FROM prc_award_win w WHERE w.rfq_id = r."Id") THEN 'Purchase' ELSE 'Cancelled' END
|
||||
WHERE r."TenderGroupId" = v_group AND r."IsDeleted" = false AND r."Status" <> 'Cancelled';
|
||||
END;
|
||||
$$;
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
-- Teklifler sekmesinde Ekle ile seçilen tedarikçi için belgenin kopyasını aynı ihalede açar: kalemler TenderLineId ile
|
||||
-- birlikte kopyalanır, fiyat tedarikçinin fiyat listesinden, para birimi ve koşullar kontak kartından gelir.
|
||||
CREATE OR REPLACE PROCEDURE public."Prc_P_PurchaseRfqCreateAlternative"(p_id uuid, p_supplier_id uuid, p_user_id uuid DEFAULT NULL)
|
||||
LANGUAGE plpgsql AS $$
|
||||
DECLARE v_tenant uuid; v_status varchar(16); v_group uuid; v_new uuid := gen_random_uuid(); v_no varchar(128);
|
||||
BEGIN
|
||||
SELECT "TenantId", "Status", "TenderGroupId" INTO v_tenant, v_status, v_group FROM "Prc_T_PurchaseRfq" WHERE "Id" = p_id;
|
||||
IF COALESCE(v_status, '') NOT IN ('Draft', 'Sent') THEN
|
||||
RAISE EXCEPTION 'Siparişe dönüştürülmüş ya da iptal edilmiş teklife alternatif eklenemez.' USING ERRCODE = 'P0001', DETAIL = '50164';
|
||||
END IF;
|
||||
IF EXISTS (SELECT 1 FROM "Prc_T_PurchaseRfq" WHERE "TenderGroupId" = v_group AND "SupplierId" = p_supplier_id AND "IsDeleted" = false AND "Status" <> 'Cancelled') THEN
|
||||
RAISE EXCEPTION 'Bu tedarikçinin ihalede zaten bir teklif talebi var.' USING ERRCODE = 'P0001', DETAIL = '50167';
|
||||
END IF;
|
||||
|
||||
CALL public."Adm_P_SequenceNext"('PurchaseRfq', v_tenant, v_no);
|
||||
|
||||
INSERT INTO "Prc_T_PurchaseRfq" ("Id", "TenantId", "RfqNo", "TenderGroupId", "SupplierId", "AgreementId", "CurrencyId", "OrderDeadline",
|
||||
"ExpectedArrival", "RequireConfirmation", "OperationTypeId", "BuyerUserId", "ProjectId", "IncotermId", "IncotermLocation", "PaymentTermId",
|
||||
"Terms", "PriceWeight", "DeliveryWeight", "CreationTime", "CreatorId", "IsDeleted")
|
||||
SELECT v_new, r."TenantId", v_no, r."TenderGroupId", c."Id", NULL, COALESCE(c."SupplierCurrency", r."CurrencyId"), r."OrderDeadline",
|
||||
r."ExpectedArrival", r."RequireConfirmation", r."OperationTypeId", r."BuyerUserId", r."ProjectId",
|
||||
COALESCE(c."PurchaseIncotermId", r."IncotermId"), COALESCE(c."PurchaseIncotermLocation", r."IncotermLocation"),
|
||||
COALESCE(c."PurchasePaymentTermId", r."PaymentTermId"), r."Terms", r."PriceWeight", r."DeliveryWeight",
|
||||
NOW() AT TIME ZONE 'UTC', p_user_id, false
|
||||
FROM "Prc_T_PurchaseRfq" r
|
||||
INNER JOIN "Adm_T_Contact" c ON c."Id" = p_supplier_id
|
||||
WHERE r."Id" = p_id;
|
||||
|
||||
INSERT INTO "Prc_T_PurchaseRfqLine" ("Id", "TenantId", "PurchaseRfqId", "TenderLineId", "ProductId", "Description", "Quantity", "UomId",
|
||||
"UnitPrice", "TaxRate", "Amount", "DeliveryDate", "MaterialRequestItemId", "CreationTime", "CreatorId", "IsDeleted")
|
||||
SELECT gen_random_uuid(), l."TenantId", v_new, l."TenderLineId", l."ProductId", l."Description", l."Quantity", l."UomId",
|
||||
COALESCE((SELECT ps."Price" FROM "Inv_T_ProductSupplier" ps
|
||||
WHERE ps."ProductId" = l."ProductId" AND ps."ContactId" = p_supplier_id AND ps."IsDeleted" = false
|
||||
ORDER BY ps."MinQuantity" LIMIT 1), 0),
|
||||
l."TaxRate", 0, l."DeliveryDate", l."MaterialRequestItemId", NOW() AT TIME ZONE 'UTC', p_user_id, false
|
||||
FROM "Prc_T_PurchaseRfqLine" l
|
||||
WHERE l."PurchaseRfqId" = p_id AND l."IsDeleted" = false;
|
||||
|
||||
CALL public."Prc_P_PurchaseRfqRecalc"(v_new);
|
||||
END;
|
||||
$$;
|
||||
|
|
@ -2,15 +2,14 @@ CREATE OR REPLACE PROCEDURE public."Prc_P_PurchaseRfqFromAgreement"(p_id uuid)
|
|||
LANGUAGE plpgsql AS $$
|
||||
DECLARE v_agr uuid; v_tenant uuid;
|
||||
BEGIN
|
||||
SELECT "AgreementId", "TenantId" INTO v_agr, v_tenant FROM "Prc_T_PurchaseOrder" WHERE "Id" = p_id;
|
||||
SELECT "AgreementId", "TenantId" INTO v_agr, v_tenant FROM "Prc_T_PurchaseRfq" WHERE "Id" = p_id AND "Status" IN ('Draft', 'Sent');
|
||||
IF v_agr IS NULL THEN RETURN; END IF;
|
||||
IF EXISTS (SELECT 1 FROM "Prc_T_PurchaseOrderLine" WHERE "PurchaseOrderId" = p_id AND "IsDeleted" = false) THEN RETURN; END IF;
|
||||
IF EXISTS (SELECT 1 FROM "Prc_T_PurchaseRfqLine" WHERE "PurchaseRfqId" = p_id AND "IsDeleted" = false) THEN RETURN; END IF;
|
||||
|
||||
INSERT INTO "Prc_T_PurchaseOrderLine" ("Id", "TenantId", "PurchaseOrderId", "ProductId", "Description", "Quantity", "UomId",
|
||||
INSERT INTO "Prc_T_PurchaseRfqLine" ("Id", "TenantId", "PurchaseRfqId", "ProductId", "Description", "Quantity", "UomId",
|
||||
"UnitPrice", "TaxRate", "Amount", "CreationTime", "IsDeleted")
|
||||
SELECT gen_random_uuid(), v_tenant, p_id, al."ProductId", al."Description",
|
||||
GREATEST(al."Quantity" - al."OrderedQuantity", 0), al."UomId", al."UnitPrice",
|
||||
COALESCE(p."PurchaseTaxRate", 0), 0, CURRENT_TIMESTAMP, false
|
||||
SELECT gen_random_uuid(), v_tenant, p_id, al."ProductId", al."Description", al."Quantity" - al."OrderedQuantity",
|
||||
al."UomId", al."UnitPrice", COALESCE(p."PurchaseTaxRate", 0), 0, NOW() AT TIME ZONE 'UTC', false
|
||||
FROM "Prc_V_PurchaseAgreementLine" al
|
||||
LEFT JOIN "Inv_T_Product" p ON p."Id" = al."ProductId"
|
||||
WHERE al."AgreementId" = v_agr AND al."IsDeleted" = false
|
||||
|
|
|
|||
20
configs/seeds/postgres/object/Prc_P_PurchaseRfqRecalc.sql
Normal file
20
configs/seeds/postgres/object/Prc_P_PurchaseRfqRecalc.sql
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
CREATE OR REPLACE PROCEDURE public."Prc_P_PurchaseRfqRecalc"(p_id uuid)
|
||||
LANGUAGE plpgsql AS $$
|
||||
BEGIN
|
||||
-- TenderLineId alternatiflere kopyalanır; ihaledeki aynı kalemi kıyasta birleştiren anahtardır.
|
||||
UPDATE "Prc_T_PurchaseRfqLine" SET "Amount" = ROUND("Quantity" * "UnitPrice", 2), "TenderLineId" = COALESCE("TenderLineId", "Id")
|
||||
WHERE "PurchaseRfqId" = p_id AND "IsDeleted" = false;
|
||||
|
||||
UPDATE "Prc_T_PurchaseRfq" r SET
|
||||
"UntaxedAmount" = COALESCE((SELECT SUM(l."Amount") FROM "Prc_T_PurchaseRfqLine" l WHERE l."PurchaseRfqId" = p_id AND l."IsDeleted" = false), 0),
|
||||
"TaxAmount" = COALESCE((SELECT SUM(ROUND(l."Amount" * l."TaxRate" / 100, 2)) FROM "Prc_T_PurchaseRfqLine" l WHERE l."PurchaseRfqId" = p_id AND l."IsDeleted" = false), 0),
|
||||
"SourceDocument" = (SELECT string_agg(DISTINCT m."RequestNo", ', ')
|
||||
FROM "Prc_T_PurchaseRfqLine" l
|
||||
INNER JOIN "Prc_T_MaterialRequestItem" i ON i."Id" = l."MaterialRequestItemId"
|
||||
INNER JOIN "Prc_T_MaterialRequest" m ON m."Id" = i."MaterialRequestId"
|
||||
WHERE l."PurchaseRfqId" = p_id AND l."IsDeleted" = false)
|
||||
WHERE r."Id" = p_id;
|
||||
|
||||
UPDATE "Prc_T_PurchaseRfq" SET "TotalAmount" = "UntaxedAmount" + "TaxAmount" WHERE "Id" = p_id;
|
||||
END;
|
||||
$$;
|
||||
46
configs/seeds/postgres/object/Prc_P_PurchaseRfqSend.sql
Normal file
46
configs/seeds/postgres/object/Prc_P_PurchaseRfqSend.sql
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
-- Tedarikçiden fiyat ve termin isteyen e-postayı bildirim kuyruğuna yazar; fiyat gönderilmez.
|
||||
CREATE OR REPLACE PROCEDURE public."Prc_P_PurchaseRfqSend"(p_id uuid, p_user_id uuid DEFAULT NULL)
|
||||
LANGUAGE plpgsql AS $$
|
||||
DECLARE v_tenant uuid; v_no varchar(32); v_email varchar(256); v_supplier varchar(256); v_deadline timestamp;
|
||||
v_subject varchar(256); v_lines text;
|
||||
BEGIN
|
||||
SELECT r."TenantId", r."RfqNo", c."Email", c."Name", r."OrderDeadline"
|
||||
INTO v_tenant, v_no, v_email, v_supplier, v_deadline
|
||||
FROM "Prc_T_PurchaseRfq" r LEFT JOIN "Adm_T_Contact" c ON c."Id" = r."SupplierId"
|
||||
WHERE r."Id" = p_id;
|
||||
|
||||
IF NOT EXISTS (SELECT 1 FROM "Prc_T_PurchaseRfqLine" WHERE "PurchaseRfqId" = p_id AND "IsDeleted" = false) THEN
|
||||
RAISE EXCEPTION '%: kalemi olmayan teklif talebi gönderilemez.', v_no USING ERRCODE = 'P0001', DETAIL = '50165';
|
||||
END IF;
|
||||
IF COALESCE(v_email, '') = '' THEN
|
||||
RAISE EXCEPTION '%: tedarikçinin (%) kontak kartında e-posta adresi yok.', v_no, v_supplier USING ERRCODE = 'P0001', DETAIL = '50166';
|
||||
END IF;
|
||||
|
||||
v_subject := 'Teklif Talebi ' || v_no;
|
||||
|
||||
SELECT string_agg('<tr><td>' || COALESCE(p."Name", '') || '</td><td>' || COALESCE(l."Description", '') || '</td><td>'
|
||||
|| TRIM(TO_CHAR(l."Quantity", 'FM999G999G990D00')) || ' ' || l."UomId" || '</td><td>'
|
||||
|| COALESCE(TO_CHAR(l."DeliveryDate", 'DD.MM.YYYY'), '') || '</td></tr>', '' ORDER BY l."CreationTime")
|
||||
INTO v_lines
|
||||
FROM "Prc_T_PurchaseRfqLine" l LEFT JOIN "Inv_T_Product" p ON p."Id" = l."ProductId"
|
||||
WHERE l."PurchaseRfqId" = p_id AND l."IsDeleted" = false;
|
||||
|
||||
-- Alıcı tedarikçinin e-postasıdır; tipin aktif Custom Mail kuralı gönderimi açar (kural kapatılırsa e-posta kuyruğa girmez).
|
||||
INSERT INTO "Adm_T_Notification" ("Id", "TenantId", "NotificationRuleId", "NotificationTypeId", "NotificationChannel", "Identifier", "Subject", "Message",
|
||||
"IsSent", "IsRead", "CreationTime", "CreatorId", "IsDeleted")
|
||||
SELECT gen_random_uuid(), v_tenant, r."Id", t."Id", r."Channel", v_email, v_subject, LEFT(
|
||||
'<p>Sayın ' || COALESCE(v_supplier, '') || ',</p><p>Aşağıdaki ürünler için birim fiyat ve teslim tarihi içeren teklifinizi'
|
||||
|| COALESCE(' en geç ' || TO_CHAR(v_deadline, 'DD.MM.YYYY HH24:MI'), '') || ' iletmenizi rica ederiz. Teklif referansı: <b>' || v_no || '</b></p>'
|
||||
|| '<table border="1" cellpadding="4" cellspacing="0"><tr><th>Ürün</th><th>Açıklama</th><th>Miktar</th><th>İstenen Termin</th></tr>'
|
||||
|| COALESCE(v_lines, '') || '</table>',
|
||||
2048), false, false, NOW() AT TIME ZONE 'UTC', p_user_id, false
|
||||
FROM "Adm_T_NotificationType" t
|
||||
INNER JOIN "Adm_T_NotificationRule" r ON r."NotificationTypeId" = t."Id" AND r."IsActive" = true AND r."IsCustomized" = false AND r."IsDeleted" = false
|
||||
AND r."RecipientType" = 'Custom' AND r."RecipientId" IS NULL AND r."Channel" = 'Mail'
|
||||
WHERE t."Name" = 'TeklifTalebiGonderildi' AND t."IsDeleted" = false AND t."TenantId" IS NOT DISTINCT FROM v_tenant;
|
||||
|
||||
UPDATE "Prc_T_PurchaseRfq" SET "LastSentDate" = NOW() AT TIME ZONE 'UTC',
|
||||
"Status" = CASE WHEN "Status" = 'Draft' THEN 'Sent' ELSE "Status" END
|
||||
WHERE "Id" = p_id;
|
||||
END;
|
||||
$$;
|
||||
37
configs/seeds/postgres/object/Prc_P_PurchaseRfqSetStatus.sql
Normal file
37
configs/seeds/postgres/object/Prc_P_PurchaseRfqSetStatus.sql
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
CREATE OR REPLACE PROCEDURE public."Prc_P_PurchaseRfqSetStatus"(p_id uuid, p_action varchar, p_user_id uuid DEFAULT NULL)
|
||||
LANGUAGE plpgsql AS $$
|
||||
DECLARE v_status varchar(16); v_group uuid; v_draft uuid;
|
||||
BEGIN
|
||||
SELECT "Status", "TenderGroupId" INTO v_status, v_group FROM "Prc_T_PurchaseRfq" WHERE "Id" = p_id;
|
||||
UPDATE "Prc_T_PurchaseRfq" SET "PendingAction" = NULL WHERE "Id" = p_id;
|
||||
|
||||
IF p_action IN ('Send', 'SendTender', 'Award') AND v_status NOT IN ('Draft', 'Sent') THEN
|
||||
RAISE EXCEPTION 'Yalnız teklif aşamasındaki (Teklif Talebi / Gönderildi) belge gönderilebilir ya da siparişe dönüştürülebilir.'
|
||||
USING ERRCODE = 'P0001', DETAIL = '50173';
|
||||
END IF;
|
||||
|
||||
IF p_action = 'Send' THEN
|
||||
CALL public."Prc_P_PurchaseRfqSend"(p_id, p_user_id);
|
||||
ELSIF p_action = 'SendTender' THEN
|
||||
-- İhalenin henüz gönderilmemiş bütün belgeleri (açık belge dahil) tedarikçilerine gider.
|
||||
FOR v_draft IN SELECT "Id" FROM "Prc_T_PurchaseRfq" WHERE "TenderGroupId" = v_group AND "IsDeleted" = false AND "Status" = 'Draft' LOOP
|
||||
CALL public."Prc_P_PurchaseRfqSend"(v_draft, p_user_id);
|
||||
END LOOP;
|
||||
ELSIF p_action = 'Award' THEN
|
||||
CALL public."Prc_P_PurchaseRfqAward"(p_id, p_user_id);
|
||||
ELSIF p_action = 'Cancel' THEN
|
||||
IF v_status = 'Purchase' THEN
|
||||
RAISE EXCEPTION 'Siparişe dönüştürülmüş teklif iptal edilemez; satınalma siparişini iptal edin.' USING ERRCODE = 'P0001', DETAIL = '50174';
|
||||
END IF;
|
||||
UPDATE "Prc_T_PurchaseRfq" SET "Status" = 'Cancelled' WHERE "Id" = p_id;
|
||||
ELSIF p_action = 'Draft' THEN
|
||||
IF v_status <> 'Cancelled' THEN
|
||||
RAISE EXCEPTION 'Yalnız iptal edilmiş teklif taslağa alınabilir.' USING ERRCODE = 'P0001', DETAIL = '50175';
|
||||
END IF;
|
||||
IF EXISTS (SELECT 1 FROM "Prc_T_PurchaseRfq" WHERE "TenderGroupId" = v_group AND "IsDeleted" = false AND "Status" = 'Purchase') THEN
|
||||
RAISE EXCEPTION 'İhale siparişe dönüştürüldüğü için teklif yeniden açılamaz.' USING ERRCODE = 'P0001', DETAIL = '50176';
|
||||
END IF;
|
||||
UPDATE "Prc_T_PurchaseRfq" SET "Status" = 'Draft' WHERE "Id" = p_id;
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
|
|
@ -3,21 +3,15 @@ CREATE TABLE IF NOT EXISTS public."Prc_T_PurchaseOrder"
|
|||
"Id" uuid NOT NULL DEFAULT gen_random_uuid(),
|
||||
"TenantId" uuid NULL,
|
||||
"OrderNo" varchar(32) NOT NULL,
|
||||
"PurchaseRfqId" uuid NULL,
|
||||
"SupplierId" uuid NOT NULL,
|
||||
"SupplierReference" varchar(64) NULL,
|
||||
"AgreementId" uuid NULL,
|
||||
"MaterialRequestId" uuid NULL,
|
||||
"CurrencyId" varchar(8) NOT NULL DEFAULT 'TRY',
|
||||
"OrderDeadline" timestamp NULL,
|
||||
"ExpectedArrival" timestamp NULL,
|
||||
"RequireConfirmation" boolean NOT NULL DEFAULT FALSE,
|
||||
"OperationTypeId" uuid NULL,
|
||||
"ConfirmDate" timestamp NULL,
|
||||
"ArrivalDate" timestamp NULL,
|
||||
"SupplierResponse" varchar(16) NOT NULL DEFAULT 'Waiting',
|
||||
"QuoteDate" timestamp NULL,
|
||||
"QuotedByUserId" uuid NULL,
|
||||
"QuoteValidUntil" date NULL,
|
||||
"BuyerUserId" uuid NOT NULL,
|
||||
"SourceDocument" varchar(512) NULL,
|
||||
"ProjectId" uuid NULL,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@ CREATE TABLE IF NOT EXISTS public."Prc_T_PurchaseOrderLine"
|
|||
"UnitPrice" numeric(18, 4) NOT NULL DEFAULT 0,
|
||||
"TaxRate" numeric(18, 4) NOT NULL DEFAULT 20,
|
||||
"Amount" numeric(18, 4) NOT NULL DEFAULT 0,
|
||||
"DeliveryDate" timestamp NULL,
|
||||
"MaterialRequestItemId" uuid NULL,
|
||||
"PurchaseRfqLineId" uuid NULL,
|
||||
"CreationTime" timestamp NOT NULL DEFAULT (NOW() AT TIME ZONE 'UTC'),
|
||||
"CreatorId" uuid NULL,
|
||||
"LastModificationTime" timestamp NULL,
|
||||
|
|
|
|||
43
configs/seeds/postgres/object/Prc_T_PurchaseRfq.sql
Normal file
43
configs/seeds/postgres/object/Prc_T_PurchaseRfq.sql
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
CREATE TABLE IF NOT EXISTS public."Prc_T_PurchaseRfq"
|
||||
(
|
||||
"Id" uuid NOT NULL DEFAULT gen_random_uuid(),
|
||||
"TenantId" uuid NULL,
|
||||
"RfqNo" varchar(32) NOT NULL,
|
||||
"TenderGroupId" uuid NULL,
|
||||
"SupplierId" uuid NOT NULL,
|
||||
"SupplierReference" varchar(64) NULL,
|
||||
"AgreementId" uuid NULL,
|
||||
"CurrencyId" varchar(8) NOT NULL DEFAULT 'TRY',
|
||||
"OrderDeadline" timestamp NULL,
|
||||
"ExpectedArrival" timestamp NULL,
|
||||
"RequireConfirmation" boolean NOT NULL DEFAULT FALSE,
|
||||
"OperationTypeId" uuid NULL,
|
||||
"SupplierResponse" varchar(16) NOT NULL DEFAULT 'Waiting',
|
||||
"QuoteDate" timestamp NULL,
|
||||
"QuoteValidUntil" date NULL,
|
||||
"BuyerUserId" uuid NOT NULL,
|
||||
"SourceDocument" varchar(512) NULL,
|
||||
"ProjectId" uuid NULL,
|
||||
"IncotermId" uuid NULL,
|
||||
"IncotermLocation" varchar(128) NULL,
|
||||
"PaymentTermId" uuid NULL,
|
||||
"Terms" text NULL,
|
||||
"PriceWeight" numeric(5, 2) NOT NULL DEFAULT 70,
|
||||
"DeliveryWeight" numeric(5, 2) NOT NULL DEFAULT 30,
|
||||
"UntaxedAmount" numeric(18, 4) NOT NULL DEFAULT 0,
|
||||
"TaxAmount" numeric(18, 4) NOT NULL DEFAULT 0,
|
||||
"TotalAmount" numeric(18, 4) NOT NULL DEFAULT 0,
|
||||
"Status" varchar(16) NOT NULL DEFAULT 'Draft',
|
||||
"PendingAction" varchar(16) NULL,
|
||||
"LastSentDate" timestamp NULL,
|
||||
"CreationTime" timestamp NOT NULL DEFAULT (NOW() AT TIME ZONE 'UTC'),
|
||||
"CreatorId" uuid NULL,
|
||||
"LastModificationTime" timestamp NULL,
|
||||
"LastModifierId" uuid NULL,
|
||||
"IsDeleted" boolean NOT NULL DEFAULT FALSE,
|
||||
"DeletionTime" timestamp NULL,
|
||||
"DeleterId" uuid NULL,
|
||||
CONSTRAINT "PK_Prc_T_PurchaseRfq" PRIMARY KEY ("Id")
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "IX_Prc_T_PurchaseRfq_TenderGroupId" ON public."Prc_T_PurchaseRfq" ("TenderGroupId");
|
||||
33
configs/seeds/postgres/object/Prc_T_PurchaseRfqLine.sql
Normal file
33
configs/seeds/postgres/object/Prc_T_PurchaseRfqLine.sql
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
CREATE TABLE IF NOT EXISTS public."Prc_T_PurchaseRfqLine"
|
||||
(
|
||||
"Id" uuid NOT NULL DEFAULT gen_random_uuid(),
|
||||
"TenantId" uuid NULL,
|
||||
"PurchaseRfqId" uuid NOT NULL,
|
||||
"TenderLineId" uuid NULL,
|
||||
"ProductId" uuid NOT NULL,
|
||||
"Description" varchar(512) NULL,
|
||||
"Quantity" numeric(18, 4) NOT NULL DEFAULT 1,
|
||||
"UomId" varchar(50) NOT NULL DEFAULT 'Adet',
|
||||
"UnitPrice" numeric(18, 4) NOT NULL DEFAULT 0,
|
||||
"TaxRate" numeric(18, 4) NOT NULL DEFAULT 20,
|
||||
"Amount" numeric(18, 4) NOT NULL DEFAULT 0,
|
||||
"DeliveryDate" timestamp NULL,
|
||||
"MaterialRequestItemId" uuid NULL,
|
||||
"IsSelected" boolean NOT NULL DEFAULT FALSE,
|
||||
"CreationTime" timestamp NOT NULL DEFAULT (NOW() AT TIME ZONE 'UTC'),
|
||||
"CreatorId" uuid NULL,
|
||||
"LastModificationTime" timestamp NULL,
|
||||
"LastModifierId" uuid NULL,
|
||||
"IsDeleted" boolean NOT NULL DEFAULT FALSE,
|
||||
"DeletionTime" timestamp NULL,
|
||||
"DeleterId" uuid NULL,
|
||||
CONSTRAINT "PK_Prc_T_PurchaseRfqLine" PRIMARY KEY ("Id")
|
||||
);
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_Prc_T_PurchaseRfqLine_PurchaseRfqId') THEN
|
||||
ALTER TABLE public."Prc_T_PurchaseRfqLine" ADD CONSTRAINT "FK_Prc_T_PurchaseRfqLine_PurchaseRfqId" FOREIGN KEY ("PurchaseRfqId") REFERENCES public."Prc_T_PurchaseRfq" ("Id") ON DELETE CASCADE ON UPDATE NO ACTION;
|
||||
END IF;
|
||||
END
|
||||
$$;
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
-- Teklife ya da siparişe aktarılabilecek talep kalemleri: onaylı talebin satınalma ile karşılanacak,
|
||||
-- bekleyen ve iptal olmayan bir teklif/siparişte yer almayan kalemi. Aktarım ve talep seçimi buradan okur.
|
||||
CREATE OR REPLACE VIEW public."Prc_V_MaterialRequestAvailableItem" AS
|
||||
SELECT i."Id", i."TenantId", i."MaterialRequestId", r."RequestNo", r."RequesterUserId", i."ProductId", i."Quantity", i."UomId",
|
||||
i."RequestReason", i."DueDate"
|
||||
FROM "Prc_T_MaterialRequestItem" i
|
||||
INNER JOIN "Prc_T_MaterialRequest" r ON r."Id" = i."MaterialRequestId"
|
||||
WHERE i."IsDeleted" = false AND r."IsDeleted" = false
|
||||
AND r."ApprovalStatus" = 'Onaylandı'
|
||||
AND i."FulfillmentMethod" = 'Purchase' AND i."LineStatus" = 'Waiting'
|
||||
AND NOT EXISTS (SELECT 1 FROM "Prc_T_PurchaseRfqLine" rl
|
||||
INNER JOIN "Prc_T_PurchaseRfq" q ON q."Id" = rl."PurchaseRfqId"
|
||||
WHERE rl."MaterialRequestItemId" = i."Id" AND rl."IsDeleted" = false
|
||||
AND q."IsDeleted" = false AND q."Status" <> 'Cancelled')
|
||||
AND NOT EXISTS (SELECT 1 FROM "Prc_T_PurchaseOrderLine" ol
|
||||
INNER JOIN "Prc_T_PurchaseOrder" o ON o."Id" = ol."PurchaseOrderId"
|
||||
WHERE ol."MaterialRequestItemId" = i."Id" AND ol."IsDeleted" = false
|
||||
AND o."IsDeleted" = false AND o."Status" <> 'Cancelled');
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
CREATE OR REPLACE VIEW public."Prc_V_MaterialRequestImportable" AS
|
||||
SELECT r."Id", r."TenantId", r."RequestNo", r."RequesterUserId", r."RequestDate",
|
||||
(SELECT COUNT(*) FROM "Prc_T_MaterialRequestItem" i
|
||||
WHERE i."MaterialRequestId" = r."Id" AND i."IsDeleted" = false
|
||||
AND i."FulfillmentMethod" = 'Purchase' AND i."LineStatus" = 'Waiting'
|
||||
AND NOT EXISTS (SELECT 1 FROM "Prc_T_PurchaseOrderLine" ol
|
||||
INNER JOIN "Prc_T_PurchaseOrder" o ON o."Id" = ol."PurchaseOrderId"
|
||||
WHERE ol."MaterialRequestItemId" = i."Id" AND ol."IsDeleted" = false
|
||||
AND o."IsDeleted" = false AND o."Status" <> 'Cancelled')) AS "ImportableCount"
|
||||
FROM "Prc_T_MaterialRequest" r
|
||||
WHERE r."IsDeleted" = false AND r."ApprovalStatus" = 'Onaylandı';
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
-- Talep Kalemleri sekmesi: aktarılabilir her talep kalemi, kalem alabilecek açık belgeyle (teklif aşamasındaki
|
||||
-- teklif talebi ya da taslak sipariş) eşlenir. Id = belge|kalem; satır işaretlenip kaydedilince Prc_P_PurchaseImportItem kopyalar.
|
||||
CREATE OR REPLACE VIEW public."Prc_V_PurchaseImportItem" AS
|
||||
SELECT d."Id"::text || '|' || a."Id"::text AS "Id", d."Id" AS "BaseId", a."TenantId", a."MaterialRequestId",
|
||||
a."RequestNo", a."RequesterUserId", a."ProductId", a."Quantity", a."UomId", a."RequestReason", a."DueDate", false AS "Transfer"
|
||||
FROM (SELECT "Id", "TenantId" FROM "Prc_T_PurchaseRfq" WHERE "IsDeleted" = false AND "Status" IN ('Draft', 'Sent')
|
||||
UNION ALL
|
||||
SELECT "Id", "TenantId" FROM "Prc_T_PurchaseOrder" WHERE "IsDeleted" = false AND "Status" = 'Draft') d
|
||||
INNER JOIN "Prc_V_MaterialRequestAvailableItem" a ON a."TenantId" IS NOT DISTINCT FROM d."TenantId";
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
CREATE OR REPLACE VIEW public."Prc_V_PurchaseOrderAlternative" AS
|
||||
SELECT DISTINCT b."Id" AS "BaseOrderId", x."Id", x."TenantId", x."OrderNo", x."SupplierId", x."Status", x."SupplierResponse",
|
||||
x."OrderDeadline", x."ExpectedArrival", x."TotalAmount", x."CurrencyId", x."IsDeleted"
|
||||
FROM "Prc_T_PurchaseOrder" b
|
||||
INNER JOIN "Prc_T_PurchaseOrderLine" bl ON bl."PurchaseOrderId" = b."Id" AND bl."IsDeleted" = false AND bl."MaterialRequestItemId" IS NOT NULL
|
||||
INNER JOIN "Prc_T_MaterialRequestItem" bi ON bi."Id" = bl."MaterialRequestItemId"
|
||||
INNER JOIN "Prc_T_MaterialRequestItem" xi ON xi."MaterialRequestId" = bi."MaterialRequestId"
|
||||
INNER JOIN "Prc_T_PurchaseOrderLine" xl ON xl."MaterialRequestItemId" = xi."Id" AND xl."IsDeleted" = false
|
||||
INNER JOIN "Prc_T_PurchaseOrder" x ON x."Id" = xl."PurchaseOrderId" AND x."Id" <> b."Id"
|
||||
WHERE b."IsDeleted" = false;
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
-- Aynı ihaledeki teklif talepleri. BaseId açık belgedir: teklif talebinde ihalenin diğer belgeleri,
|
||||
-- satınalma siparişinde kaynak teklifin ihalesindeki bütün belgeler.
|
||||
CREATE OR REPLACE VIEW public."Prc_V_PurchaseRfqAlternative" AS
|
||||
SELECT b."Id" AS "BaseId", x."Id", x."TenantId", x."RfqNo", x."SupplierId", x."Status", x."SupplierResponse",
|
||||
x."OrderDeadline", x."ExpectedArrival", x."UntaxedAmount", x."TotalAmount", x."CurrencyId", x."IsDeleted"
|
||||
FROM "Prc_T_PurchaseRfq" b
|
||||
INNER JOIN "Prc_T_PurchaseRfq" x ON x."TenderGroupId" = b."TenderGroupId" AND x."Id" <> b."Id"
|
||||
WHERE b."IsDeleted" = false
|
||||
UNION ALL
|
||||
SELECT o."Id", x."Id", x."TenantId", x."RfqNo", x."SupplierId", x."Status", x."SupplierResponse",
|
||||
x."OrderDeadline", x."ExpectedArrival", x."UntaxedAmount", x."TotalAmount", x."CurrencyId", x."IsDeleted"
|
||||
FROM "Prc_T_PurchaseOrder" o
|
||||
INNER JOIN "Prc_T_PurchaseRfq" s ON s."Id" = o."PurchaseRfqId"
|
||||
INNER JOIN "Prc_T_PurchaseRfq" x ON x."TenderGroupId" = s."TenderGroupId"
|
||||
WHERE o."IsDeleted" = false;
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
-- İhale kalemlerinin tedarikçi bazında kıyası. BaseId ihaledeki herhangi bir belgedir; her belge aynı tabloyu görür.
|
||||
-- Fiyat kurla TL'ye çevrilir (Sas_H_Currency.Rate = 1 birimin TL karşılığı), termin ihalenin açılışından gün olarak ölçülür.
|
||||
-- Puan = Fiyat ağırlığı × en düşük fiyat / fiyat + Termin ağırlığı × en kısa termin / termin (ağırlıklar ihalenin kök belgesinden).
|
||||
-- Fiyatı girilmemiş, terminsiz, "Teklif Vermedi" ya da iptal edilmiş belgenin satırı puanlanmaz.
|
||||
CREATE OR REPLACE VIEW public."Prc_V_PurchaseRfqComparison" AS
|
||||
WITH "Lines" AS (
|
||||
SELECT b."Id" AS "BaseId", l."Id", l."TenantId", COALESCE(l."TenderLineId", l."Id") AS "TenderLineId", l."PurchaseRfqId",
|
||||
x."RfqNo", x."SupplierId", x."Status", x."SupplierResponse", l."ProductId", l."Description", l."Quantity", l."UomId",
|
||||
l."UnitPrice", x."CurrencyId", CAST(l."UnitPrice" * COALESCE(c."Rate", 1) AS numeric(18, 4)) AS "PriceTry",
|
||||
COALESCE(l."DeliveryDate", x."ExpectedArrival") AS "DeliveryDate",
|
||||
GREATEST(COALESCE(l."DeliveryDate", x."ExpectedArrival")::date - g."CreationTime"::date, 1) AS "LeadDays",
|
||||
g."PriceWeight", g."DeliveryWeight", l."IsSelected", l."IsDeleted",
|
||||
CASE WHEN x."Status" <> 'Cancelled' AND x."SupplierResponse" <> 'NotQuoted' AND l."UnitPrice" > 0
|
||||
AND COALESCE(l."DeliveryDate", x."ExpectedArrival") IS NOT NULL THEN 1 ELSE 0 END AS "IsEligible"
|
||||
FROM "Prc_T_PurchaseRfq" b
|
||||
INNER JOIN "Prc_T_PurchaseRfq" g ON g."Id" = b."TenderGroupId"
|
||||
INNER JOIN "Prc_T_PurchaseRfq" x ON x."TenderGroupId" = b."TenderGroupId" AND x."IsDeleted" = false
|
||||
INNER JOIN "Prc_T_PurchaseRfqLine" l ON l."PurchaseRfqId" = x."Id" AND l."IsDeleted" = false
|
||||
LEFT JOIN "Sas_H_Currency" c ON c."Id" = x."CurrencyId"
|
||||
WHERE b."IsDeleted" = false
|
||||
), "Scored" AS (
|
||||
SELECT "Lines".*,
|
||||
CASE WHEN "IsEligible" = 1 THEN CAST(
|
||||
"PriceWeight" * MIN(CASE WHEN "IsEligible" = 1 THEN "PriceTry" END) OVER (PARTITION BY "BaseId", "TenderLineId") / "PriceTry"
|
||||
+ "DeliveryWeight" * MIN(CASE WHEN "IsEligible" = 1 THEN "LeadDays" END) OVER (PARTITION BY "BaseId", "TenderLineId") * 1.0 / "LeadDays"
|
||||
AS numeric(9, 2)) END AS "Score"
|
||||
FROM "Lines"
|
||||
)
|
||||
SELECT "BaseId", "Id", "TenantId", "TenderLineId", "PurchaseRfqId", "RfqNo", "SupplierId", "Status", "SupplierResponse", "ProductId",
|
||||
"Description", "Quantity", "UomId", "UnitPrice", "CurrencyId", "PriceTry", "DeliveryDate", "LeadDays", "Score",
|
||||
("IsEligible" = 1 AND ROW_NUMBER() OVER (PARTITION BY "BaseId", "TenderLineId"
|
||||
ORDER BY "IsEligible" DESC, "Score" DESC NULLS LAST, "PriceTry", "LeadDays") = 1) AS "IsRecommended",
|
||||
"IsSelected", "IsDeleted"
|
||||
FROM "Scored";
|
||||
47
configs/seeds/sql/object/Adm_P_SequenceNext.sql
Normal file
47
configs/seeds/sql/object/Adm_P_SequenceNext.sql
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
-- SQL tarafında açılan belgenin (yordamın ürettiği teklif, sipariş) numarasını numaratörden alır.
|
||||
-- Biçim ve sıfırlama kuralı Sequence.GetNextSequence ile birebir aynıdır; biri değişirse diğeri de değişir.
|
||||
CREATE OR ALTER PROCEDURE [dbo].[Adm_P_SequenceNext]
|
||||
@Name nvarchar(128),
|
||||
@TenantId uniqueidentifier,
|
||||
@Value nvarchar(128) OUTPUT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
DECLARE @Id uniqueidentifier, @Reset int, @Period nvarchar(16), @Number bigint, @Step int, @Padding int,
|
||||
@Prefix nvarchar(64), @Suffix nvarchar(64), @Template nvarchar(256), @NumberText nvarchar(32),
|
||||
@Now datetime = GETDATE(), @Msg nvarchar(256);
|
||||
|
||||
SELECT TOP 1 @Id = Id, @Reset = ResetPeriod
|
||||
FROM Adm_T_Sequence WITH (UPDLOCK, HOLDLOCK)
|
||||
WHERE Name = @Name AND IsActive = 1 AND IsDeleted = 0
|
||||
AND (TenantId = @TenantId OR (TenantId IS NULL AND @TenantId IS NULL));
|
||||
IF @Id IS NULL
|
||||
BEGIN
|
||||
SET @Msg = CONCAT(N'Numaratör bulunamadı: ', @Name);
|
||||
THROW 50190, @Msg, 1;
|
||||
END
|
||||
|
||||
SET @Period = CASE @Reset WHEN 1 THEN FORMAT(@Now, 'yyyy') WHEN 2 THEN FORMAT(@Now, 'yyyyMM') WHEN 3 THEN FORMAT(@Now, 'yyyyMMdd')
|
||||
WHEN 4 THEN FORMAT(@Now, 'yyyyMMddHH') WHEN 5 THEN FORMAT(@Now, 'yyyyMMddHHmm') END;
|
||||
|
||||
SELECT @Number = CASE WHEN @Period IS NOT NULL AND ISNULL(LastPeriodKey, N'') <> @Period THEN StartNumber ELSE NextNumber END,
|
||||
@Step = IncrementStep, @Padding = PaddingSize, @Prefix = ISNULL(Prefix, N''), @Suffix = ISNULL(Suffix, N''),
|
||||
@Template = CASE WHEN LTRIM(ISNULL(FormatTemplate, N'')) = N'' THEN N'{Prefix}{Number}{Suffix}' ELSE FormatTemplate END
|
||||
FROM Adm_T_Sequence WHERE Id = @Id;
|
||||
|
||||
UPDATE Adm_T_Sequence
|
||||
SET NextNumber = @Number + @Step, LastPeriodKey = ISNULL(@Period, LastPeriodKey)
|
||||
WHERE Id = @Id;
|
||||
|
||||
SET @NumberText = CAST(@Number AS nvarchar(32));
|
||||
IF LEN(@NumberText) < @Padding SET @NumberText = RIGHT(REPLICATE(N'0', @Padding) + @NumberText, @Padding);
|
||||
|
||||
-- Belirteçler büyük/küçük harf duyarlıdır ({MM} ay, {mm} dakika).
|
||||
SET @Value = REPLACE(REPLACE(REPLACE(@Template COLLATE Latin1_General_BIN2, N'{Prefix}', @Prefix), N'{Suffix}', @Suffix), N'{Number}', @NumberText);
|
||||
SET @Value = REPLACE(REPLACE(@Value COLLATE Latin1_General_BIN2, N'{yyyy}', FORMAT(@Now, 'yyyy')), N'{yy}', FORMAT(@Now, 'yy'));
|
||||
SET @Value = REPLACE(REPLACE(@Value COLLATE Latin1_General_BIN2, N'{MM}', FORMAT(@Now, 'MM')), N'{M}', CAST(MONTH(@Now) AS nvarchar(2)));
|
||||
SET @Value = REPLACE(REPLACE(@Value COLLATE Latin1_General_BIN2, N'{dd}', FORMAT(@Now, 'dd')), N'{d}', CAST(DAY(@Now) AS nvarchar(2)));
|
||||
SET @Value = REPLACE(REPLACE(@Value COLLATE Latin1_General_BIN2, N'{HH}', FORMAT(@Now, 'HH')), N'{H}', CAST(DATEPART(hour, @Now) AS nvarchar(2)));
|
||||
SET @Value = REPLACE(REPLACE(@Value COLLATE Latin1_General_BIN2, N'{mm}', FORMAT(@Now, 'mm')), N'{m}', CAST(DATEPART(minute, @Now) AS nvarchar(2)));
|
||||
SET @Value = REPLACE(REPLACE(@Value COLLATE Latin1_General_BIN2, N'{ss}', FORMAT(@Now, 'ss')), N'{s}', CAST(DATEPART(second, @Now) AS nvarchar(2)));
|
||||
END
|
||||
52
configs/seeds/sql/object/Prc_P_PurchaseImportItem.sql
Normal file
52
configs/seeds/sql/object/Prc_P_PurchaseImportItem.sql
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
-- Talep Kalemleri sekmesinde işaretlenen kalemi (@Key = belge|kalem) teklif talebine ya da taslak siparişe kopyalar.
|
||||
-- Fiyat: sözleşme kalemi › tedarikçi fiyatı › 0; termin talebin istenen tarihidir.
|
||||
CREATE OR ALTER PROCEDURE [dbo].[Prc_P_PurchaseImportItem]
|
||||
@Key nvarchar(80),
|
||||
@Transfer bit = 1
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
IF ISNULL(@Transfer, 0) = 0 RETURN;
|
||||
|
||||
DECLARE @DocId uniqueidentifier = TRY_CAST(LEFT(@Key, 36) AS uniqueidentifier),
|
||||
@ItemId uniqueidentifier = TRY_CAST(RIGHT(@Key, 36) AS uniqueidentifier),
|
||||
@IsOrder bit = 0, @Tenant uniqueidentifier, @Supplier uniqueidentifier, @Agr uniqueidentifier, @Status nvarchar(16),
|
||||
@ProductId uniqueidentifier, @Description nvarchar(512), @Quantity decimal(18, 4), @UomId nvarchar(50),
|
||||
@UnitPrice decimal(18, 4), @TaxRate decimal(18, 4), @DueDate datetime;
|
||||
|
||||
SELECT @Tenant = TenantId, @Supplier = SupplierId, @Agr = AgreementId, @Status = Status
|
||||
FROM Prc_T_PurchaseRfq WHERE Id = @DocId AND IsDeleted = 0 AND Status IN ('Draft', 'Sent');
|
||||
IF @Status IS NULL
|
||||
SELECT @Tenant = TenantId, @Supplier = SupplierId, @Agr = AgreementId, @Status = Status, @IsOrder = 1
|
||||
FROM Prc_T_PurchaseOrder WHERE Id = @DocId AND IsDeleted = 0 AND Status = 'Draft';
|
||||
IF @Status IS NULL
|
||||
THROW 50161, N'Talep kalemi yalnız teklif aşamasındaki teklif talebine ya da taslak siparişe aktarılabilir.', 1;
|
||||
|
||||
SELECT @ProductId = a.ProductId, @Description = a.RequestReason, @Quantity = a.Quantity, @UomId = a.UomId, @DueDate = a.DueDate,
|
||||
@TaxRate = ISNULL(p.PurchaseTaxRate, 0),
|
||||
@UnitPrice = COALESCE((SELECT TOP 1 al.UnitPrice FROM Prc_T_PurchaseAgreementLine al
|
||||
WHERE al.AgreementId = @Agr AND al.ProductId = a.ProductId AND al.IsDeleted = 0),
|
||||
(SELECT TOP 1 ps.Price FROM Inv_T_ProductSupplier ps
|
||||
WHERE ps.ProductId = a.ProductId AND ps.ContactId = @Supplier AND ps.IsDeleted = 0
|
||||
ORDER BY ps.MinQuantity), 0)
|
||||
FROM Prc_V_MaterialRequestAvailableItem a
|
||||
LEFT JOIN Inv_T_Product p ON p.Id = a.ProductId
|
||||
WHERE a.Id = @ItemId AND (a.TenantId = @Tenant OR (a.TenantId IS NULL AND @Tenant IS NULL));
|
||||
IF @ProductId IS NULL
|
||||
THROW 50162, N'Talep kalemi artık aktarılamaz: başka bir teklife ya da siparişe aktarılmış veya talep değişmiş.', 1;
|
||||
|
||||
IF @IsOrder = 1
|
||||
BEGIN
|
||||
INSERT INTO Prc_T_PurchaseOrderLine (Id, TenantId, PurchaseOrderId, ProductId, Description, Quantity, UomId,
|
||||
UnitPrice, TaxRate, Amount, DeliveryDate, MaterialRequestItemId, CreationTime, IsDeleted)
|
||||
VALUES (NEWID(), @Tenant, @DocId, @ProductId, @Description, @Quantity, @UomId, @UnitPrice, @TaxRate, 0, @DueDate, @ItemId, GETUTCDATE(), 0);
|
||||
EXEC Prc_P_PurchaseOrderRecalc @DocId;
|
||||
END
|
||||
ELSE
|
||||
BEGIN
|
||||
INSERT INTO Prc_T_PurchaseRfqLine (Id, TenantId, PurchaseRfqId, ProductId, Description, Quantity, UomId,
|
||||
UnitPrice, TaxRate, Amount, DeliveryDate, MaterialRequestItemId, CreationTime, IsDeleted)
|
||||
VALUES (NEWID(), @Tenant, @DocId, @ProductId, @Description, @Quantity, @UomId, @UnitPrice, @TaxRate, 0, @DueDate, @ItemId, GETUTCDATE(), 0);
|
||||
EXEC Prc_P_PurchaseRfqRecalc @DocId;
|
||||
END
|
||||
END
|
||||
|
|
@ -4,8 +4,7 @@ CREATE OR ALTER PROCEDURE [dbo].[Prc_P_PurchaseOrderAfterSave]
|
|||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
DECLARE @Req uniqueidentifier, @Act nvarchar(16), @Agr uniqueidentifier;
|
||||
|
||||
DECLARE @Act nvarchar(16) = (SELECT PendingAction FROM Prc_T_PurchaseOrder WHERE Id = @Id);
|
||||
UPDATE o SET
|
||||
PaymentTermId = ISNULL(o.PaymentTermId, c.PurchasePaymentTermId),
|
||||
IncotermId = ISNULL(o.IncotermId, c.PurchaseIncotermId),
|
||||
|
|
@ -15,9 +14,7 @@ BEGIN
|
|||
INNER JOIN Adm_T_Contact c ON c.Id = o.SupplierId
|
||||
WHERE o.Id = @Id;
|
||||
|
||||
SELECT @Req = MaterialRequestId, @Act = PendingAction, @Agr = AgreementId FROM Prc_T_PurchaseOrder WHERE Id = @Id;
|
||||
IF @Agr IS NOT NULL EXEC Prc_P_PurchaseRfqFromAgreement @Id;
|
||||
IF @Req IS NOT NULL EXEC Prc_P_PurchaseOrderImportRequest @Id;
|
||||
EXEC Prc_P_PurchaseOrderRecalc @Id;
|
||||
-- Durum butonlari islemi PendingAction alanina yazip ekranin guncelleme ucuyla kaydeder.
|
||||
IF @Act IS NOT NULL EXEC Prc_P_PurchaseOrderSetStatus @Id, @Act, @UserId;
|
||||
END
|
||||
|
|
|
|||
|
|
@ -1,39 +0,0 @@
|
|||
CREATE OR ALTER PROCEDURE [dbo].[Prc_P_PurchaseOrderImportRequest]
|
||||
@Id uniqueidentifier
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
DECLARE @Req uniqueidentifier, @Tenant uniqueidentifier, @Supplier uniqueidentifier, @Agr uniqueidentifier, @Status nvarchar(16), @Cnt int;
|
||||
|
||||
SELECT @Req = MaterialRequestId, @Tenant = TenantId, @Supplier = SupplierId, @Agr = AgreementId, @Status = Status
|
||||
FROM Prc_T_PurchaseOrder WHERE Id = @Id;
|
||||
IF @Req IS NULL RETURN;
|
||||
IF @Status = 'Cancelled'
|
||||
THROW 50101, N'İptal edilmiş belgeye talepten aktarım yapılamaz.', 1;
|
||||
|
||||
INSERT INTO Prc_T_PurchaseOrderLine (Id, TenantId, PurchaseOrderId, ProductId, Description, Quantity, UomId,
|
||||
UnitPrice, TaxRate, Amount, MaterialRequestItemId, CreationTime, IsDeleted)
|
||||
SELECT NEWID(), @Tenant, @Id, i.ProductId, i.RequestReason, i.Quantity, i.UomId,
|
||||
COALESCE((SELECT TOP 1 al.UnitPrice FROM Prc_T_PurchaseAgreementLine al
|
||||
WHERE al.AgreementId = @Agr AND al.ProductId = i.ProductId AND al.IsDeleted = 0),
|
||||
(SELECT TOP 1 ps.Price FROM Inv_T_ProductSupplier ps
|
||||
WHERE ps.ProductId = i.ProductId AND ps.ContactId = @Supplier AND ps.IsDeleted = 0
|
||||
ORDER BY ps.MinQuantity), 0),
|
||||
ISNULL(p.PurchaseTaxRate, 0), 0, i.Id, GETUTCDATE(), 0
|
||||
FROM Prc_T_MaterialRequestItem i
|
||||
INNER JOIN Prc_T_MaterialRequest r ON r.Id = i.MaterialRequestId
|
||||
LEFT JOIN Inv_T_Product p ON p.Id = i.ProductId
|
||||
WHERE i.MaterialRequestId = @Req AND i.IsDeleted = 0
|
||||
AND r.ApprovalStatus = N'Onaylandı'
|
||||
AND i.FulfillmentMethod = 'Purchase' AND i.LineStatus = 'Waiting'
|
||||
AND NOT EXISTS (SELECT 1 FROM Prc_T_PurchaseOrderLine ol
|
||||
INNER JOIN Prc_T_PurchaseOrder o ON o.Id = ol.PurchaseOrderId
|
||||
WHERE ol.MaterialRequestItemId = i.Id AND ol.IsDeleted = 0
|
||||
AND o.IsDeleted = 0 AND o.Status <> 'Cancelled');
|
||||
SET @Cnt = @@ROWCOUNT;
|
||||
|
||||
UPDATE Prc_T_PurchaseOrder SET MaterialRequestId = NULL WHERE Id = @Id;
|
||||
|
||||
IF @Cnt = 0
|
||||
THROW 50102, N'Seçilen talepte aktarılacak kalem yok (onaylı, Satınalma ile karşılanacak, bekleyen ve başka belgede olmayan kalem bulunamadı).', 1;
|
||||
END
|
||||
|
|
@ -7,16 +7,19 @@ BEGIN
|
|||
UPDATE Prc_T_PurchaseOrderLine SET Amount = ROUND(Quantity * UnitPrice, 2)
|
||||
WHERE PurchaseOrderId = @Id AND IsDeleted = 0;
|
||||
|
||||
-- Kaynak: teklif talebinden gelen siparişte teklif no, doğrudan yazılan siparişte talep numaraları.
|
||||
UPDATE o SET
|
||||
UntaxedAmount = ISNULL((SELECT SUM(l.Amount) FROM Prc_T_PurchaseOrderLine l WHERE l.PurchaseOrderId = @Id AND l.IsDeleted = 0), 0),
|
||||
TaxAmount = ISNULL((SELECT SUM(ROUND(l.Amount * l.TaxRate / 100, 2)) FROM Prc_T_PurchaseOrderLine l WHERE l.PurchaseOrderId = @Id AND l.IsDeleted = 0), 0),
|
||||
SourceDocument = STUFF((SELECT DISTINCT N', ' + r.RequestNo
|
||||
FROM Prc_T_PurchaseOrderLine l
|
||||
INNER JOIN Prc_T_MaterialRequestItem i ON i.Id = l.MaterialRequestItemId
|
||||
INNER JOIN Prc_T_MaterialRequest r ON r.Id = i.MaterialRequestId
|
||||
WHERE l.PurchaseOrderId = @Id AND l.IsDeleted = 0
|
||||
FOR XML PATH(''), TYPE).value('.', 'nvarchar(512)'), 1, 2, N'')
|
||||
SourceDocument = COALESCE(q.RfqNo,
|
||||
STUFF((SELECT DISTINCT N', ' + m.RequestNo
|
||||
FROM Prc_T_PurchaseOrderLine l
|
||||
INNER JOIN Prc_T_MaterialRequestItem i ON i.Id = l.MaterialRequestItemId
|
||||
INNER JOIN Prc_T_MaterialRequest m ON m.Id = i.MaterialRequestId
|
||||
WHERE l.PurchaseOrderId = @Id AND l.IsDeleted = 0
|
||||
FOR XML PATH(''), TYPE).value('.', 'nvarchar(512)'), 1, 2, N''))
|
||||
FROM Prc_T_PurchaseOrder o
|
||||
LEFT JOIN Prc_T_PurchaseRfq q ON q.Id = o.PurchaseRfqId
|
||||
WHERE o.Id = @Id;
|
||||
|
||||
UPDATE Prc_T_PurchaseOrder SET TotalAmount = UntaxedAmount + TaxAmount WHERE Id = @Id;
|
||||
|
|
|
|||
|
|
@ -4,47 +4,42 @@ CREATE OR ALTER PROCEDURE [dbo].[Prc_P_PurchaseOrderSend]
|
|||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
DECLARE @Tenant uniqueidentifier, @No nvarchar(32), @Status nvarchar(16), @Email nvarchar(256), @Supplier nvarchar(256),
|
||||
@TypeName nvarchar(64), @Type uniqueidentifier, @Subject nvarchar(256), @Lines nvarchar(max), @Total decimal(18,4), @Cur nvarchar(8);
|
||||
DECLARE @Tenant uniqueidentifier, @No nvarchar(32), @Email nvarchar(256), @Supplier nvarchar(256),
|
||||
@Subject nvarchar(256), @Lines nvarchar(MAX), @Total decimal(18, 4), @Cur nvarchar(8);
|
||||
|
||||
SELECT @Tenant = o.TenantId, @No = o.OrderNo, @Status = o.Status, @Email = c.Email, @Supplier = c.Name,
|
||||
@Total = o.TotalAmount, @Cur = o.CurrencyId
|
||||
SELECT @Tenant = o.TenantId, @No = o.OrderNo, @Email = c.Email, @Supplier = c.Name, @Total = o.TotalAmount, @Cur = o.CurrencyId
|
||||
FROM Prc_T_PurchaseOrder o LEFT JOIN Adm_T_Contact c ON c.Id = o.SupplierId
|
||||
WHERE o.Id = @Id;
|
||||
|
||||
IF NOT EXISTS (SELECT 1 FROM Prc_T_PurchaseOrderLine WHERE PurchaseOrderId = @Id AND IsDeleted = 0)
|
||||
THROW 50111, N'Kalemi olmayan belge gönderilemez.', 1;
|
||||
THROW 50185, N'Kalemi olmayan sipariş gönderilemez.', 1;
|
||||
IF ISNULL(@Email, N'') = N''
|
||||
THROW 50112, N'Tedarikçinin kontak kartında e-posta adresi yok.', 1;
|
||||
THROW 50186, N'Tedarikçinin kontak kartında e-posta adresi yok.', 1;
|
||||
|
||||
IF @Status = 'Purchase'
|
||||
SELECT @TypeName = N'Prc.PurchaseOrderSent', @Subject = N'Satınalma Siparişi ' + @No;
|
||||
ELSE
|
||||
SELECT @TypeName = N'Prc.RfqSent', @Subject = N'Teklif Talebi ' + @No;
|
||||
SET @Subject = N'Satınalma Siparişi ' + @No;
|
||||
|
||||
SELECT TOP 1 @Type = Id FROM Adm_T_NotificationType
|
||||
WHERE Name = @TypeName AND IsDeleted = 0 AND (TenantId = @Tenant OR (TenantId IS NULL AND @Tenant IS NULL));
|
||||
|
||||
SELECT @Lines = (SELECT N'<tr><td>' + ISNULL(p.Name, N'') + N'</td><td>' + ISNULL(l.Description, N'') + N'</td><td style="text-align:right">'
|
||||
+ FORMAT(l.Quantity, 'N2', 'tr-TR') + N' ' + l.UomId + N'</td><td style="text-align:right">'
|
||||
+ FORMAT(l.UnitPrice, 'N2', 'tr-TR') + N'</td><td style="text-align:right">%'
|
||||
+ FORMAT(l.TaxRate, 'N0', 'tr-TR') + N'</td><td style="text-align:right">'
|
||||
+ FORMAT(l.Amount, 'N2', 'tr-TR') + N'</td></tr>'
|
||||
SELECT @Lines = (SELECT N'<tr><td>' + ISNULL(p.Name, N'') + N'</td><td>' + ISNULL(l.Description, N'') + N'</td><td>'
|
||||
+ FORMAT(l.Quantity, 'N2', 'tr-TR') + N' ' + l.UomId + N'</td><td>'
|
||||
+ FORMAT(l.UnitPrice, 'N2', 'tr-TR') + N'</td><td>%'
|
||||
+ FORMAT(l.TaxRate, 'N0', 'tr-TR') + N'</td><td>'
|
||||
+ FORMAT(l.Amount, 'N2', 'tr-TR') + N'</td><td>' + ISNULL(FORMAT(l.DeliveryDate, 'dd.MM.yyyy'), N'') + N'</td></tr>'
|
||||
FROM Prc_T_PurchaseOrderLine l LEFT JOIN Inv_T_Product p ON p.Id = l.ProductId
|
||||
WHERE l.PurchaseOrderId = @Id AND l.IsDeleted = 0
|
||||
ORDER BY l.CreationTime
|
||||
FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)');
|
||||
|
||||
INSERT INTO Adm_T_Notification (Id, TenantId, NotificationTypeId, NotificationChannel, Identifier, Subject, Message,
|
||||
-- Alıcı tedarikçinin e-postasıdır; tipin aktif Custom Mail kuralı gönderimi açar (kural kapatılırsa e-posta kuyruğa girmez).
|
||||
INSERT INTO Adm_T_Notification (Id, TenantId, NotificationRuleId, NotificationTypeId, NotificationChannel, Identifier, Subject, Message,
|
||||
IsSent, IsRead, CreationTime, CreatorId, IsDeleted)
|
||||
VALUES (NEWID(), @Tenant, @Type, N'Mail', @Email, @Subject,
|
||||
SELECT NEWID(), @Tenant, r.Id, t.Id, r.Channel, @Email, @Subject, LEFT(
|
||||
N'<p>Sayın ' + ISNULL(@Supplier, N'') + N',</p><p>' + @Subject + N' aşağıda bilgilerinize sunulmuştur.</p>'
|
||||
+ N'<table border="1" cellpadding="4" cellspacing="0"><tr><th>Ürün</th><th>Açıklama</th><th>Miktar</th><th>Birim Fiyat</th><th>KDV</th><th>Tutar</th></tr>'
|
||||
+ N'<table border="1" cellpadding="4" cellspacing="0"><tr><th>Ürün</th><th>Açıklama</th><th>Miktar</th><th>Birim Fiyat</th><th>KDV</th><th>Tutar</th><th>Termin</th></tr>'
|
||||
+ ISNULL(@Lines, N'') + N'</table><p><b>Toplam: ' + FORMAT(@Total, 'N2', 'tr-TR') + N' ' + @Cur + N'</b></p>',
|
||||
0, 0, GETUTCDATE(), @UserId, 0);
|
||||
2048), 0, 0, GETUTCDATE(), @UserId, 0
|
||||
FROM Adm_T_NotificationType t
|
||||
INNER JOIN Adm_T_NotificationRule r ON r.NotificationTypeId = t.Id AND r.IsActive = 1 AND r.IsCustomized = 0 AND r.IsDeleted = 0
|
||||
AND r.RecipientType = N'Custom' AND r.RecipientId IS NULL AND r.Channel = N'Mail'
|
||||
WHERE t.Name = N'SatinalmaSiparisiGonderildi' AND t.IsDeleted = 0 AND (t.TenantId = @Tenant OR (t.TenantId IS NULL AND @Tenant IS NULL));
|
||||
|
||||
UPDATE Prc_T_PurchaseOrder
|
||||
SET LastSentDate = GETUTCDATE(),
|
||||
Status = CASE WHEN Status = 'Draft' THEN 'Sent' ELSE Status END
|
||||
WHERE Id = @Id;
|
||||
UPDATE Prc_T_PurchaseOrder SET LastSentDate = GETUTCDATE() WHERE Id = @Id;
|
||||
END
|
||||
|
|
|
|||
|
|
@ -9,23 +9,23 @@ BEGIN
|
|||
SELECT @Status = Status FROM Prc_T_PurchaseOrder WHERE Id = @Id;
|
||||
UPDATE Prc_T_PurchaseOrder SET PendingAction = NULL WHERE Id = @Id;
|
||||
|
||||
IF @Action = 'Send'
|
||||
IF @Action = 'Confirm'
|
||||
BEGIN
|
||||
IF @Status = 'Cancelled' THROW 50121, N'İptal edilmiş belge gönderilemez.', 1;
|
||||
EXEC Prc_P_PurchaseOrderSend @Id, @UserId;
|
||||
END
|
||||
ELSE IF @Action = 'Confirm'
|
||||
BEGIN
|
||||
IF @Status NOT IN ('Draft', 'Sent') THROW 50122, N'Yalnız teklif aşamasındaki belge siparişe çevrilebilir.', 1;
|
||||
IF @Status <> 'Draft' THROW 50181, N'Yalnız taslak sipariş onaylanabilir.', 1;
|
||||
IF NOT EXISTS (SELECT 1 FROM Prc_T_PurchaseOrderLine WHERE PurchaseOrderId = @Id AND IsDeleted = 0)
|
||||
THROW 50123, N'Kalemi olmayan teklif onaylanamaz.', 1;
|
||||
THROW 50182, N'Kalemi olmayan sipariş onaylanamaz.', 1;
|
||||
UPDATE Prc_T_PurchaseOrder SET Status = 'Purchase', ConfirmDate = GETUTCDATE() WHERE Id = @Id;
|
||||
END
|
||||
ELSE IF @Action = 'Send'
|
||||
BEGIN
|
||||
IF @Status = 'Cancelled' THROW 50183, N'İptal edilmiş sipariş gönderilemez.', 1;
|
||||
EXEC Prc_P_PurchaseOrderSend @Id, @UserId;
|
||||
END
|
||||
ELSE IF @Action = 'Cancel'
|
||||
UPDATE Prc_T_PurchaseOrder SET Status = 'Cancelled' WHERE Id = @Id;
|
||||
ELSE IF @Action = 'Draft'
|
||||
BEGIN
|
||||
IF @Status <> 'Cancelled' THROW 50124, N'Yalnız iptal edilmiş belge taslağa alınabilir.', 1;
|
||||
IF @Status <> 'Cancelled' THROW 50184, N'Yalnız iptal edilmiş sipariş taslağa alınabilir.', 1;
|
||||
UPDATE Prc_T_PurchaseOrder SET Status = 'Draft', ConfirmDate = NULL WHERE Id = @Id;
|
||||
END
|
||||
END
|
||||
|
|
|
|||
34
configs/seeds/sql/object/Prc_P_PurchaseRfqAfterSave.sql
Normal file
34
configs/seeds/sql/object/Prc_P_PurchaseRfqAfterSave.sql
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
CREATE OR ALTER PROCEDURE [dbo].[Prc_P_PurchaseRfqAfterSave]
|
||||
@Id uniqueidentifier,
|
||||
@UserId uniqueidentifier = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
DECLARE @Act nvarchar(16) = (SELECT PendingAction FROM Prc_T_PurchaseRfq WHERE Id = @Id);
|
||||
IF EXISTS (SELECT 1 FROM Prc_T_PurchaseRfq WHERE Id = @Id AND PriceWeight + DeliveryWeight <> 100)
|
||||
THROW 50153, N'Fiyat ve termin ağırlıklarının toplamı 100 olmalıdır.', 1;
|
||||
|
||||
-- İhalenin kökü ilk belgedir; alternatifler kökün Id'sini taşır.
|
||||
UPDATE r SET
|
||||
TenderGroupId = ISNULL(r.TenderGroupId, r.Id),
|
||||
QuoteDate = CASE WHEN r.SupplierResponse <> 'Waiting' THEN ISNULL(r.QuoteDate, GETUTCDATE()) ELSE r.QuoteDate END,
|
||||
PaymentTermId = ISNULL(r.PaymentTermId, c.PurchasePaymentTermId),
|
||||
IncotermId = ISNULL(r.IncotermId, c.PurchaseIncotermId),
|
||||
IncotermLocation = ISNULL(r.IncotermLocation, c.PurchaseIncotermLocation),
|
||||
BuyerUserId = CASE WHEN r.LastModificationTime IS NULL AND c.BuyerUserId IS NOT NULL THEN c.BuyerUserId ELSE r.BuyerUserId END
|
||||
FROM Prc_T_PurchaseRfq r
|
||||
INNER JOIN Adm_T_Contact c ON c.Id = r.SupplierId
|
||||
WHERE r.Id = @Id;
|
||||
|
||||
-- Kıyas ağırlıkları ihale geneli tek değerdir; hangi belgede değişirse diğerlerine yazılır.
|
||||
UPDATE x SET PriceWeight = r.PriceWeight, DeliveryWeight = r.DeliveryWeight
|
||||
FROM Prc_T_PurchaseRfq x
|
||||
INNER JOIN Prc_T_PurchaseRfq r ON r.Id = @Id
|
||||
WHERE x.TenderGroupId = r.TenderGroupId AND x.Id <> r.Id
|
||||
AND (x.PriceWeight <> r.PriceWeight OR x.DeliveryWeight <> r.DeliveryWeight);
|
||||
|
||||
EXEC Prc_P_PurchaseRfqFromAgreement @Id;
|
||||
EXEC Prc_P_PurchaseRfqRecalc @Id;
|
||||
-- Durum butonlari islemi PendingAction alanina yazip ekranin guncelleme ucuyla kaydeder.
|
||||
IF @Act IS NOT NULL EXEC Prc_P_PurchaseRfqSetStatus @Id, @Act, @UserId;
|
||||
END
|
||||
67
configs/seeds/sql/object/Prc_P_PurchaseRfqAward.sql
Normal file
67
configs/seeds/sql/object/Prc_P_PurchaseRfqAward.sql
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
-- İhaleyi kalem bazında siparişe çevirir: kalemin Seçili satırı varsa o, yoksa Önerilen satır kazanır.
|
||||
-- Kazanan her teklif talebi için bir satınalma siparişi açılır (Kaynak = teklif no); kazanan teklif
|
||||
-- Satınalma Siparişi, hiç kalem kazanamayan teklif İptal Edildi olur.
|
||||
CREATE OR ALTER PROCEDURE [dbo].[Prc_P_PurchaseRfqAward]
|
||||
@Id uniqueidentifier,
|
||||
@UserId uniqueidentifier = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
DECLARE @Group uniqueidentifier, @Tenant uniqueidentifier, @Rfq uniqueidentifier, @Po uniqueidentifier, @No nvarchar(128);
|
||||
DECLARE @Win TABLE (LineId uniqueidentifier PRIMARY KEY, RfqId uniqueidentifier NOT NULL);
|
||||
|
||||
SELECT @Group = TenderGroupId, @Tenant = TenantId FROM Prc_T_PurchaseRfq WHERE Id = @Id;
|
||||
IF EXISTS (SELECT 1 FROM Prc_T_PurchaseRfq WHERE TenderGroupId = @Group AND IsDeleted = 0 AND Status = 'Purchase')
|
||||
THROW 50171, N'Bu ihale zaten siparişe dönüştürüldü.', 1;
|
||||
|
||||
INSERT INTO @Win (LineId, RfqId)
|
||||
SELECT c.Id, c.PurchaseRfqId
|
||||
FROM Prc_V_PurchaseRfqComparison c
|
||||
WHERE c.BaseId = @Id AND c.Status <> 'Cancelled'
|
||||
AND (c.IsSelected = 1
|
||||
OR (c.IsRecommended = 1 AND NOT EXISTS (SELECT 1 FROM Prc_V_PurchaseRfqComparison s
|
||||
WHERE s.BaseId = @Id AND s.TenderLineId = c.TenderLineId
|
||||
AND s.IsSelected = 1 AND s.Status <> 'Cancelled')));
|
||||
IF NOT EXISTS (SELECT 1 FROM @Win)
|
||||
THROW 50172, N'Siparişe dönüştürülecek kalem yok: tedarikçi fiyat ve terminlerini girin ya da Fiyat Karşılaştırması sekmesinde kazananı seçin.', 1;
|
||||
|
||||
DECLARE winners CURSOR LOCAL FAST_FORWARD FOR SELECT DISTINCT RfqId FROM @Win;
|
||||
OPEN winners;
|
||||
FETCH NEXT FROM winners INTO @Rfq;
|
||||
WHILE @@FETCH_STATUS = 0
|
||||
BEGIN
|
||||
SET @Po = NEWID();
|
||||
EXEC Adm_P_SequenceNext N'PurchaseOrder1', @Tenant, @No OUTPUT;
|
||||
|
||||
INSERT INTO Prc_T_PurchaseOrder (Id, TenantId, OrderNo, PurchaseRfqId, SupplierId, SupplierReference, AgreementId, CurrencyId,
|
||||
ExpectedArrival, OperationTypeId, ConfirmDate, BuyerUserId, ProjectId, IncotermId, IncotermLocation, PaymentTermId, Terms,
|
||||
Status, CreationTime, CreatorId, IsDeleted)
|
||||
SELECT @Po, TenantId, @No, Id, SupplierId, SupplierReference, AgreementId, CurrencyId,
|
||||
ExpectedArrival, OperationTypeId, GETUTCDATE(), BuyerUserId, ProjectId, IncotermId, IncotermLocation, PaymentTermId, Terms,
|
||||
'Purchase', GETUTCDATE(), @UserId, 0
|
||||
FROM Prc_T_PurchaseRfq WHERE Id = @Rfq;
|
||||
|
||||
INSERT INTO Prc_T_PurchaseOrderLine (Id, TenantId, PurchaseOrderId, ProductId, Description, Quantity, UomId, UnitPrice, TaxRate,
|
||||
Amount, DeliveryDate, MaterialRequestItemId, PurchaseRfqLineId, CreationTime, CreatorId, IsDeleted)
|
||||
SELECT NEWID(), l.TenantId, @Po, l.ProductId, l.Description, l.Quantity, l.UomId, l.UnitPrice, l.TaxRate,
|
||||
0, l.DeliveryDate, l.MaterialRequestItemId, l.Id, GETUTCDATE(), @UserId, 0
|
||||
FROM Prc_T_PurchaseRfqLine l
|
||||
INNER JOIN @Win w ON w.LineId = l.Id
|
||||
WHERE w.RfqId = @Rfq;
|
||||
|
||||
EXEC Prc_P_PurchaseOrderRecalc @Po;
|
||||
FETCH NEXT FROM winners INTO @Rfq;
|
||||
END
|
||||
CLOSE winners;
|
||||
DEALLOCATE winners;
|
||||
|
||||
UPDATE l SET IsSelected = CASE WHEN w.LineId IS NULL THEN 0 ELSE 1 END
|
||||
FROM Prc_T_PurchaseRfqLine l
|
||||
INNER JOIN Prc_T_PurchaseRfq r ON r.Id = l.PurchaseRfqId
|
||||
LEFT JOIN @Win w ON w.LineId = l.Id
|
||||
WHERE r.TenderGroupId = @Group AND r.IsDeleted = 0 AND r.Status <> 'Cancelled';
|
||||
|
||||
UPDATE r SET Status = CASE WHEN EXISTS (SELECT 1 FROM @Win w WHERE w.RfqId = r.Id) THEN 'Purchase' ELSE 'Cancelled' END
|
||||
FROM Prc_T_PurchaseRfq r
|
||||
WHERE r.TenderGroupId = @Group AND r.IsDeleted = 0 AND r.Status <> 'Cancelled';
|
||||
END
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
-- Teklifler sekmesinde Ekle ile seçilen tedarikçi için belgenin kopyasını aynı ihalede açar: kalemler TenderLineId ile
|
||||
-- birlikte kopyalanır, fiyat tedarikçinin fiyat listesinden, para birimi ve koşullar kontak kartından gelir.
|
||||
CREATE OR ALTER PROCEDURE [dbo].[Prc_P_PurchaseRfqCreateAlternative]
|
||||
@Id uniqueidentifier,
|
||||
@SupplierId uniqueidentifier,
|
||||
@UserId uniqueidentifier = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
DECLARE @Tenant uniqueidentifier, @Status nvarchar(16), @Group uniqueidentifier, @New uniqueidentifier = NEWID(), @No nvarchar(128);
|
||||
|
||||
SELECT @Tenant = TenantId, @Status = Status, @Group = TenderGroupId FROM Prc_T_PurchaseRfq WHERE Id = @Id;
|
||||
IF ISNULL(@Status, '') NOT IN ('Draft', 'Sent')
|
||||
THROW 50164, N'Siparişe dönüştürülmüş ya da iptal edilmiş teklife alternatif eklenemez.', 1;
|
||||
IF EXISTS (SELECT 1 FROM Prc_T_PurchaseRfq WHERE TenderGroupId = @Group AND SupplierId = @SupplierId AND IsDeleted = 0 AND Status <> 'Cancelled')
|
||||
THROW 50167, N'Bu tedarikçinin ihalede zaten bir teklif talebi var.', 1;
|
||||
|
||||
EXEC Adm_P_SequenceNext N'PurchaseRfq', @Tenant, @No OUTPUT;
|
||||
|
||||
INSERT INTO Prc_T_PurchaseRfq (Id, TenantId, RfqNo, TenderGroupId, SupplierId, AgreementId, CurrencyId, OrderDeadline,
|
||||
ExpectedArrival, RequireConfirmation, OperationTypeId, BuyerUserId, ProjectId, IncotermId, IncotermLocation, PaymentTermId,
|
||||
Terms, PriceWeight, DeliveryWeight, CreationTime, CreatorId, IsDeleted)
|
||||
SELECT @New, r.TenantId, @No, r.TenderGroupId, c.Id, NULL, COALESCE(c.SupplierCurrency, r.CurrencyId), r.OrderDeadline,
|
||||
r.ExpectedArrival, r.RequireConfirmation, r.OperationTypeId, r.BuyerUserId, r.ProjectId,
|
||||
COALESCE(c.PurchaseIncotermId, r.IncotermId), COALESCE(c.PurchaseIncotermLocation, r.IncotermLocation),
|
||||
COALESCE(c.PurchasePaymentTermId, r.PaymentTermId), r.Terms, r.PriceWeight, r.DeliveryWeight, GETUTCDATE(), @UserId, 0
|
||||
FROM Prc_T_PurchaseRfq r
|
||||
INNER JOIN Adm_T_Contact c ON c.Id = @SupplierId
|
||||
WHERE r.Id = @Id;
|
||||
|
||||
INSERT INTO Prc_T_PurchaseRfqLine (Id, TenantId, PurchaseRfqId, TenderLineId, ProductId, Description, Quantity, UomId,
|
||||
UnitPrice, TaxRate, Amount, DeliveryDate, MaterialRequestItemId, CreationTime, CreatorId, IsDeleted)
|
||||
SELECT NEWID(), l.TenantId, @New, l.TenderLineId, l.ProductId, l.Description, l.Quantity, l.UomId,
|
||||
ISNULL((SELECT TOP 1 ps.Price FROM Inv_T_ProductSupplier ps
|
||||
WHERE ps.ProductId = l.ProductId AND ps.ContactId = @SupplierId AND ps.IsDeleted = 0
|
||||
ORDER BY ps.MinQuantity), 0),
|
||||
l.TaxRate, 0, l.DeliveryDate, l.MaterialRequestItemId, GETUTCDATE(), @UserId, 0
|
||||
FROM Prc_T_PurchaseRfqLine l
|
||||
WHERE l.PurchaseRfqId = @Id AND l.IsDeleted = 0;
|
||||
|
||||
EXEC Prc_P_PurchaseRfqRecalc @New;
|
||||
END
|
||||
|
|
@ -4,14 +4,13 @@ AS
|
|||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
DECLARE @Agr uniqueidentifier, @Tenant uniqueidentifier;
|
||||
SELECT @Agr = AgreementId, @Tenant = TenantId FROM Prc_T_PurchaseOrder WHERE Id = @Id;
|
||||
SELECT @Agr = AgreementId, @Tenant = TenantId FROM Prc_T_PurchaseRfq WHERE Id = @Id AND Status IN ('Draft', 'Sent');
|
||||
IF @Agr IS NULL RETURN;
|
||||
IF EXISTS (SELECT 1 FROM Prc_T_PurchaseOrderLine WHERE PurchaseOrderId = @Id AND IsDeleted = 0) RETURN;
|
||||
IF EXISTS (SELECT 1 FROM Prc_T_PurchaseRfqLine WHERE PurchaseRfqId = @Id AND IsDeleted = 0) RETURN;
|
||||
|
||||
INSERT INTO Prc_T_PurchaseOrderLine (Id, TenantId, PurchaseOrderId, ProductId, Description, Quantity, UomId,
|
||||
INSERT INTO Prc_T_PurchaseRfqLine (Id, TenantId, PurchaseRfqId, ProductId, Description, Quantity, UomId,
|
||||
UnitPrice, TaxRate, Amount, CreationTime, IsDeleted)
|
||||
SELECT NEWID(), @Tenant, @Id, al.ProductId, al.Description,
|
||||
CASE WHEN al.Quantity - al.OrderedQuantity > 0 THEN al.Quantity - al.OrderedQuantity ELSE 0 END,
|
||||
SELECT NEWID(), @Tenant, @Id, al.ProductId, al.Description, al.Quantity - al.OrderedQuantity,
|
||||
al.UomId, al.UnitPrice, ISNULL(p.PurchaseTaxRate, 0), 0, GETUTCDATE(), 0
|
||||
FROM Prc_V_PurchaseAgreementLine al
|
||||
LEFT JOIN Inv_T_Product p ON p.Id = al.ProductId
|
||||
|
|
|
|||
24
configs/seeds/sql/object/Prc_P_PurchaseRfqRecalc.sql
Normal file
24
configs/seeds/sql/object/Prc_P_PurchaseRfqRecalc.sql
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
CREATE OR ALTER PROCEDURE [dbo].[Prc_P_PurchaseRfqRecalc]
|
||||
@Id uniqueidentifier
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
-- TenderLineId alternatiflere kopyalanır; ihaledeki aynı kalemi kıyasta birleştiren anahtardır.
|
||||
UPDATE Prc_T_PurchaseRfqLine SET Amount = ROUND(Quantity * UnitPrice, 2), TenderLineId = ISNULL(TenderLineId, Id)
|
||||
WHERE PurchaseRfqId = @Id AND IsDeleted = 0;
|
||||
|
||||
UPDATE r SET
|
||||
UntaxedAmount = ISNULL((SELECT SUM(l.Amount) FROM Prc_T_PurchaseRfqLine l WHERE l.PurchaseRfqId = @Id AND l.IsDeleted = 0), 0),
|
||||
TaxAmount = ISNULL((SELECT SUM(ROUND(l.Amount * l.TaxRate / 100, 2)) FROM Prc_T_PurchaseRfqLine l WHERE l.PurchaseRfqId = @Id AND l.IsDeleted = 0), 0),
|
||||
SourceDocument = STUFF((SELECT DISTINCT N', ' + m.RequestNo
|
||||
FROM Prc_T_PurchaseRfqLine l
|
||||
INNER JOIN Prc_T_MaterialRequestItem i ON i.Id = l.MaterialRequestItemId
|
||||
INNER JOIN Prc_T_MaterialRequest m ON m.Id = i.MaterialRequestId
|
||||
WHERE l.PurchaseRfqId = @Id AND l.IsDeleted = 0
|
||||
FOR XML PATH(''), TYPE).value('.', 'nvarchar(512)'), 1, 2, N'')
|
||||
FROM Prc_T_PurchaseRfq r
|
||||
WHERE r.Id = @Id;
|
||||
|
||||
UPDATE Prc_T_PurchaseRfq SET TotalAmount = UntaxedAmount + TaxAmount WHERE Id = @Id;
|
||||
END
|
||||
53
configs/seeds/sql/object/Prc_P_PurchaseRfqSend.sql
Normal file
53
configs/seeds/sql/object/Prc_P_PurchaseRfqSend.sql
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
-- Tedarikçiden fiyat ve termin isteyen e-postayı bildirim kuyruğuna yazar; fiyat gönderilmez.
|
||||
CREATE OR ALTER PROCEDURE [dbo].[Prc_P_PurchaseRfqSend]
|
||||
@Id uniqueidentifier,
|
||||
@UserId uniqueidentifier = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
DECLARE @Tenant uniqueidentifier, @No nvarchar(32), @Email nvarchar(256), @Supplier nvarchar(256), @Deadline datetime,
|
||||
@Subject nvarchar(256), @Lines nvarchar(MAX), @Msg nvarchar(512);
|
||||
|
||||
SELECT @Tenant = r.TenantId, @No = r.RfqNo, @Email = c.Email, @Supplier = c.Name, @Deadline = r.OrderDeadline
|
||||
FROM Prc_T_PurchaseRfq r LEFT JOIN Adm_T_Contact c ON c.Id = r.SupplierId
|
||||
WHERE r.Id = @Id;
|
||||
|
||||
IF NOT EXISTS (SELECT 1 FROM Prc_T_PurchaseRfqLine WHERE PurchaseRfqId = @Id AND IsDeleted = 0)
|
||||
BEGIN
|
||||
SET @Msg = CONCAT(@No, N': kalemi olmayan teklif talebi gönderilemez.');
|
||||
THROW 50165, @Msg, 1;
|
||||
END
|
||||
IF ISNULL(@Email, N'') = N''
|
||||
BEGIN
|
||||
SET @Msg = CONCAT(@No, N': tedarikçinin (', @Supplier, N') kontak kartında e-posta adresi yok.');
|
||||
THROW 50166, @Msg, 1;
|
||||
END
|
||||
|
||||
SET @Subject = N'Teklif Talebi ' + @No;
|
||||
|
||||
SELECT @Lines = (SELECT N'<tr><td>' + ISNULL(p.Name, N'') + N'</td><td>' + ISNULL(l.Description, N'') + N'</td><td>'
|
||||
+ FORMAT(l.Quantity, 'N2', 'tr-TR') + N' ' + l.UomId + N'</td><td>'
|
||||
+ ISNULL(FORMAT(l.DeliveryDate, 'dd.MM.yyyy'), N'') + N'</td></tr>'
|
||||
FROM Prc_T_PurchaseRfqLine l LEFT JOIN Inv_T_Product p ON p.Id = l.ProductId
|
||||
WHERE l.PurchaseRfqId = @Id AND l.IsDeleted = 0
|
||||
ORDER BY l.CreationTime
|
||||
FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)');
|
||||
|
||||
-- Alıcı tedarikçinin e-postasıdır; tipin aktif Custom Mail kuralı gönderimi açar (kural kapatılırsa e-posta kuyruğa girmez).
|
||||
INSERT INTO Adm_T_Notification (Id, TenantId, NotificationRuleId, NotificationTypeId, NotificationChannel, Identifier, Subject, Message,
|
||||
IsSent, IsRead, CreationTime, CreatorId, IsDeleted)
|
||||
SELECT NEWID(), @Tenant, r.Id, t.Id, r.Channel, @Email, @Subject, LEFT(
|
||||
N'<p>Sayın ' + ISNULL(@Supplier, N'') + N',</p><p>Aşağıdaki ürünler için birim fiyat ve teslim tarihi içeren teklifinizi'
|
||||
+ ISNULL(N' en geç ' + FORMAT(@Deadline, 'dd.MM.yyyy HH:mm'), N'') + N' iletmenizi rica ederiz. Teklif referansı: <b>' + @No + N'</b></p>'
|
||||
+ N'<table border="1" cellpadding="4" cellspacing="0"><tr><th>Ürün</th><th>Açıklama</th><th>Miktar</th><th>İstenen Termin</th></tr>'
|
||||
+ ISNULL(@Lines, N'') + N'</table>',
|
||||
2048), 0, 0, GETUTCDATE(), @UserId, 0
|
||||
FROM Adm_T_NotificationType t
|
||||
INNER JOIN Adm_T_NotificationRule r ON r.NotificationTypeId = t.Id AND r.IsActive = 1 AND r.IsCustomized = 0 AND r.IsDeleted = 0
|
||||
AND r.RecipientType = N'Custom' AND r.RecipientId IS NULL AND r.Channel = N'Mail'
|
||||
WHERE t.Name = N'TeklifTalebiGonderildi' AND t.IsDeleted = 0 AND (t.TenantId = @Tenant OR (t.TenantId IS NULL AND @Tenant IS NULL));
|
||||
|
||||
UPDATE Prc_T_PurchaseRfq
|
||||
SET LastSentDate = GETUTCDATE(), Status = CASE WHEN Status = 'Draft' THEN 'Sent' ELSE Status END
|
||||
WHERE Id = @Id;
|
||||
END
|
||||
46
configs/seeds/sql/object/Prc_P_PurchaseRfqSetStatus.sql
Normal file
46
configs/seeds/sql/object/Prc_P_PurchaseRfqSetStatus.sql
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
CREATE OR ALTER PROCEDURE [dbo].[Prc_P_PurchaseRfqSetStatus]
|
||||
@Id uniqueidentifier,
|
||||
@Action nvarchar(16),
|
||||
@UserId uniqueidentifier = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
DECLARE @Status nvarchar(16), @Group uniqueidentifier, @Draft uniqueidentifier;
|
||||
SELECT @Status = Status, @Group = TenderGroupId FROM Prc_T_PurchaseRfq WHERE Id = @Id;
|
||||
UPDATE Prc_T_PurchaseRfq SET PendingAction = NULL WHERE Id = @Id;
|
||||
|
||||
IF @Action IN ('Send', 'SendTender', 'Award') AND @Status NOT IN ('Draft', 'Sent')
|
||||
THROW 50173, N'Yalnız teklif aşamasındaki (Teklif Talebi / Gönderildi) belge gönderilebilir ya da siparişe dönüştürülebilir.', 1;
|
||||
|
||||
IF @Action = 'Send'
|
||||
EXEC Prc_P_PurchaseRfqSend @Id, @UserId;
|
||||
ELSE IF @Action = 'SendTender'
|
||||
BEGIN
|
||||
-- İhalenin henüz gönderilmemiş bütün belgeleri (açık belge dahil) tedarikçilerine gider.
|
||||
DECLARE drafts CURSOR LOCAL FAST_FORWARD FOR
|
||||
SELECT Id FROM Prc_T_PurchaseRfq WHERE TenderGroupId = @Group AND IsDeleted = 0 AND Status = 'Draft';
|
||||
OPEN drafts;
|
||||
FETCH NEXT FROM drafts INTO @Draft;
|
||||
WHILE @@FETCH_STATUS = 0
|
||||
BEGIN
|
||||
EXEC Prc_P_PurchaseRfqSend @Draft, @UserId;
|
||||
FETCH NEXT FROM drafts INTO @Draft;
|
||||
END
|
||||
CLOSE drafts;
|
||||
DEALLOCATE drafts;
|
||||
END
|
||||
ELSE IF @Action = 'Award'
|
||||
EXEC Prc_P_PurchaseRfqAward @Id, @UserId;
|
||||
ELSE IF @Action = 'Cancel'
|
||||
BEGIN
|
||||
IF @Status = 'Purchase' THROW 50174, N'Siparişe dönüştürülmüş teklif iptal edilemez; satınalma siparişini iptal edin.', 1;
|
||||
UPDATE Prc_T_PurchaseRfq SET Status = 'Cancelled' WHERE Id = @Id;
|
||||
END
|
||||
ELSE IF @Action = 'Draft'
|
||||
BEGIN
|
||||
IF @Status <> 'Cancelled' THROW 50175, N'Yalnız iptal edilmiş teklif taslağa alınabilir.', 1;
|
||||
IF EXISTS (SELECT 1 FROM Prc_T_PurchaseRfq WHERE TenderGroupId = @Group AND IsDeleted = 0 AND Status = 'Purchase')
|
||||
THROW 50176, N'İhale siparişe dönüştürüldüğü için teklif yeniden açılamaz.', 1;
|
||||
UPDATE Prc_T_PurchaseRfq SET Status = 'Draft' WHERE Id = @Id;
|
||||
END
|
||||
END
|
||||
|
|
@ -5,21 +5,15 @@ BEGIN
|
|||
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
|
||||
[TenantId] uniqueidentifier NULL,
|
||||
[OrderNo] nvarchar(32) NOT NULL,
|
||||
[PurchaseRfqId] uniqueidentifier NULL,
|
||||
[SupplierId] uniqueidentifier NOT NULL,
|
||||
[SupplierReference] nvarchar(64) NULL,
|
||||
[AgreementId] uniqueidentifier NULL,
|
||||
[MaterialRequestId] uniqueidentifier NULL,
|
||||
[CurrencyId] nvarchar(8) NOT NULL DEFAULT 'TRY',
|
||||
[OrderDeadline] datetime NULL,
|
||||
[ExpectedArrival] datetime NULL,
|
||||
[RequireConfirmation] bit NOT NULL DEFAULT 0,
|
||||
[OperationTypeId] uniqueidentifier NULL,
|
||||
[ConfirmDate] datetime NULL,
|
||||
[ArrivalDate] datetime NULL,
|
||||
[SupplierResponse] nvarchar(16) NOT NULL DEFAULT 'Waiting',
|
||||
[QuoteDate] datetime NULL,
|
||||
[QuotedByUserId] uniqueidentifier NULL,
|
||||
[QuoteValidUntil] date NULL,
|
||||
[BuyerUserId] uniqueidentifier NOT NULL,
|
||||
[SourceDocument] nvarchar(512) NULL,
|
||||
[ProjectId] uniqueidentifier NULL,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@ BEGIN
|
|||
[UnitPrice] decimal(18, 4) NOT NULL DEFAULT 0,
|
||||
[TaxRate] decimal(18, 4) NOT NULL DEFAULT 20,
|
||||
[Amount] decimal(18, 4) NOT NULL DEFAULT 0,
|
||||
[DeliveryDate] datetime NULL,
|
||||
[MaterialRequestItemId] uniqueidentifier NULL,
|
||||
[PurchaseRfqLineId] uniqueidentifier NULL,
|
||||
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
|
||||
[CreatorId] uniqueidentifier NULL,
|
||||
[LastModificationTime] datetime2 NULL,
|
||||
|
|
|
|||
54
configs/seeds/sql/object/Prc_T_PurchaseRfq.sql
Normal file
54
configs/seeds/sql/object/Prc_T_PurchaseRfq.sql
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
IF OBJECT_ID(N'[dbo].[Prc_T_PurchaseRfq]', 'U') IS NULL
|
||||
BEGIN
|
||||
CREATE TABLE [dbo].[Prc_T_PurchaseRfq]
|
||||
(
|
||||
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
|
||||
[TenantId] uniqueidentifier NULL,
|
||||
[RfqNo] nvarchar(32) NOT NULL,
|
||||
[TenderGroupId] uniqueidentifier NULL,
|
||||
[SupplierId] uniqueidentifier NOT NULL,
|
||||
[SupplierReference] nvarchar(64) NULL,
|
||||
[AgreementId] uniqueidentifier NULL,
|
||||
[CurrencyId] nvarchar(8) NOT NULL DEFAULT 'TRY',
|
||||
[OrderDeadline] datetime NULL,
|
||||
[ExpectedArrival] datetime NULL,
|
||||
[RequireConfirmation] bit NOT NULL DEFAULT 0,
|
||||
[OperationTypeId] uniqueidentifier NULL,
|
||||
[SupplierResponse] nvarchar(16) NOT NULL DEFAULT 'Waiting',
|
||||
[QuoteDate] datetime NULL,
|
||||
[QuoteValidUntil] date NULL,
|
||||
[BuyerUserId] uniqueidentifier NOT NULL,
|
||||
[SourceDocument] nvarchar(512) NULL,
|
||||
[ProjectId] uniqueidentifier NULL,
|
||||
[IncotermId] uniqueidentifier NULL,
|
||||
[IncotermLocation] nvarchar(128) NULL,
|
||||
[PaymentTermId] uniqueidentifier NULL,
|
||||
[Terms] nvarchar(MAX) NULL,
|
||||
[PriceWeight] decimal(5, 2) NOT NULL DEFAULT 70,
|
||||
[DeliveryWeight] decimal(5, 2) NOT NULL DEFAULT 30,
|
||||
[UntaxedAmount] decimal(18, 4) NOT NULL DEFAULT 0,
|
||||
[TaxAmount] decimal(18, 4) NOT NULL DEFAULT 0,
|
||||
[TotalAmount] decimal(18, 4) NOT NULL DEFAULT 0,
|
||||
[Status] nvarchar(16) NOT NULL DEFAULT 'Draft',
|
||||
[PendingAction] nvarchar(16) NULL,
|
||||
[LastSentDate] datetime NULL,
|
||||
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
|
||||
[CreatorId] uniqueidentifier NULL,
|
||||
[LastModificationTime] datetime2 NULL,
|
||||
[LastModifierId] uniqueidentifier NULL,
|
||||
[IsDeleted] bit NOT NULL DEFAULT 0,
|
||||
[DeletionTime] datetime2 NULL,
|
||||
[DeleterId] uniqueidentifier NULL,
|
||||
CONSTRAINT [PK_Prc_T_PurchaseRfq] PRIMARY KEY NONCLUSTERED
|
||||
(
|
||||
[Id] ASC
|
||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
|
||||
) ON [PRIMARY]
|
||||
END
|
||||
GO
|
||||
|
||||
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_Prc_T_PurchaseRfq_TenderGroupId' AND object_id = OBJECT_ID(N'[dbo].[Prc_T_PurchaseRfq]'))
|
||||
BEGIN
|
||||
CREATE INDEX [IX_Prc_T_PurchaseRfq_TenderGroupId] ON [dbo].[Prc_T_PurchaseRfq] ([TenderGroupId]);
|
||||
END
|
||||
GO
|
||||
38
configs/seeds/sql/object/Prc_T_PurchaseRfqLine.sql
Normal file
38
configs/seeds/sql/object/Prc_T_PurchaseRfqLine.sql
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
IF OBJECT_ID(N'[dbo].[Prc_T_PurchaseRfqLine]', 'U') IS NULL
|
||||
BEGIN
|
||||
CREATE TABLE [dbo].[Prc_T_PurchaseRfqLine]
|
||||
(
|
||||
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
|
||||
[TenantId] uniqueidentifier NULL,
|
||||
[PurchaseRfqId] uniqueidentifier NOT NULL,
|
||||
[TenderLineId] uniqueidentifier NULL,
|
||||
[ProductId] uniqueidentifier NOT NULL,
|
||||
[Description] nvarchar(512) NULL,
|
||||
[Quantity] decimal(18, 4) NOT NULL DEFAULT 1,
|
||||
[UomId] nvarchar(50) NOT NULL DEFAULT 'Adet',
|
||||
[UnitPrice] decimal(18, 4) NOT NULL DEFAULT 0,
|
||||
[TaxRate] decimal(18, 4) NOT NULL DEFAULT 20,
|
||||
[Amount] decimal(18, 4) NOT NULL DEFAULT 0,
|
||||
[DeliveryDate] datetime NULL,
|
||||
[MaterialRequestItemId] uniqueidentifier NULL,
|
||||
[IsSelected] bit NOT NULL DEFAULT 0,
|
||||
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
|
||||
[CreatorId] uniqueidentifier NULL,
|
||||
[LastModificationTime] datetime2 NULL,
|
||||
[LastModifierId] uniqueidentifier NULL,
|
||||
[IsDeleted] bit NOT NULL DEFAULT 0,
|
||||
[DeletionTime] datetime2 NULL,
|
||||
[DeleterId] uniqueidentifier NULL,
|
||||
CONSTRAINT [PK_Prc_T_PurchaseRfqLine] PRIMARY KEY NONCLUSTERED
|
||||
(
|
||||
[Id] ASC
|
||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
|
||||
) ON [PRIMARY]
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'[dbo].[FK_Prc_T_PurchaseRfqLine_PurchaseRfqId]', 'F') IS NULL
|
||||
BEGIN
|
||||
ALTER TABLE [dbo].[Prc_T_PurchaseRfqLine] ADD CONSTRAINT [FK_Prc_T_PurchaseRfqLine_PurchaseRfqId] FOREIGN KEY ([PurchaseRfqId]) REFERENCES [dbo].[Prc_T_PurchaseRfq] ([Id]) ON DELETE CASCADE ON UPDATE NO ACTION;
|
||||
END
|
||||
GO
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
-- Teklife ya da siparişe aktarılabilecek talep kalemleri: onaylı talebin satınalma ile karşılanacak,
|
||||
-- bekleyen ve iptal olmayan bir teklif/siparişte yer almayan kalemi. Aktarım ve talep seçimi buradan okur.
|
||||
CREATE OR ALTER VIEW [dbo].[Prc_V_MaterialRequestAvailableItem] AS
|
||||
SELECT i.Id, i.TenantId, i.MaterialRequestId, r.RequestNo, r.RequesterUserId, i.ProductId, i.Quantity, i.UomId,
|
||||
i.RequestReason, i.DueDate
|
||||
FROM Prc_T_MaterialRequestItem i
|
||||
INNER JOIN Prc_T_MaterialRequest r ON r.Id = i.MaterialRequestId
|
||||
WHERE i.IsDeleted = 0 AND r.IsDeleted = 0
|
||||
AND r.ApprovalStatus = N'Onaylandı'
|
||||
AND i.FulfillmentMethod = 'Purchase' AND i.LineStatus = 'Waiting'
|
||||
AND NOT EXISTS (SELECT 1 FROM Prc_T_PurchaseRfqLine rl
|
||||
INNER JOIN Prc_T_PurchaseRfq q ON q.Id = rl.PurchaseRfqId
|
||||
WHERE rl.MaterialRequestItemId = i.Id AND rl.IsDeleted = 0
|
||||
AND q.IsDeleted = 0 AND q.Status <> 'Cancelled')
|
||||
AND NOT EXISTS (SELECT 1 FROM Prc_T_PurchaseOrderLine ol
|
||||
INNER JOIN Prc_T_PurchaseOrder o ON o.Id = ol.PurchaseOrderId
|
||||
WHERE ol.MaterialRequestItemId = i.Id AND ol.IsDeleted = 0
|
||||
AND o.IsDeleted = 0 AND o.Status <> 'Cancelled')
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
CREATE OR ALTER VIEW [dbo].[Prc_V_MaterialRequestImportable] AS
|
||||
SELECT r.Id, r.TenantId, r.RequestNo, r.RequesterUserId, r.RequestDate,
|
||||
(SELECT COUNT(*) FROM Prc_T_MaterialRequestItem i
|
||||
WHERE i.MaterialRequestId = r.Id AND i.IsDeleted = 0
|
||||
AND i.FulfillmentMethod = 'Purchase' AND i.LineStatus = 'Waiting'
|
||||
AND NOT EXISTS (SELECT 1 FROM Prc_T_PurchaseOrderLine ol
|
||||
INNER JOIN Prc_T_PurchaseOrder o ON o.Id = ol.PurchaseOrderId
|
||||
WHERE ol.MaterialRequestItemId = i.Id AND ol.IsDeleted = 0
|
||||
AND o.IsDeleted = 0 AND o.Status <> 'Cancelled')) AS ImportableCount
|
||||
FROM Prc_T_MaterialRequest r
|
||||
WHERE r.IsDeleted = 0 AND r.ApprovalStatus = N'Onaylandı'
|
||||
9
configs/seeds/sql/object/Prc_V_PurchaseImportItem.sql
Normal file
9
configs/seeds/sql/object/Prc_V_PurchaseImportItem.sql
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
-- Talep Kalemleri sekmesi: aktarılabilir her talep kalemi, kalem alabilecek açık belgeyle (teklif aşamasındaki
|
||||
-- teklif talebi ya da taslak sipariş) eşlenir. Id = belge|kalem; satır işaretlenip kaydedilince Prc_P_PurchaseImportItem kopyalar.
|
||||
CREATE OR ALTER VIEW [dbo].[Prc_V_PurchaseImportItem] AS
|
||||
SELECT CONCAT(CAST(d.Id AS nvarchar(36)), '|', CAST(a.Id AS nvarchar(36))) AS Id, d.Id AS BaseId, a.TenantId, a.MaterialRequestId,
|
||||
a.RequestNo, a.RequesterUserId, a.ProductId, a.Quantity, a.UomId, a.RequestReason, a.DueDate, CAST(0 AS bit) AS Transfer
|
||||
FROM (SELECT Id, TenantId FROM Prc_T_PurchaseRfq WHERE IsDeleted = 0 AND Status IN ('Draft', 'Sent')
|
||||
UNION ALL
|
||||
SELECT Id, TenantId FROM Prc_T_PurchaseOrder WHERE IsDeleted = 0 AND Status = 'Draft') d
|
||||
INNER JOIN Prc_V_MaterialRequestAvailableItem a ON a.TenantId = d.TenantId OR (a.TenantId IS NULL AND d.TenantId IS NULL)
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
CREATE OR ALTER VIEW [dbo].[Prc_V_PurchaseOrderAlternative] AS
|
||||
SELECT DISTINCT b.Id AS BaseOrderId, x.Id, x.TenantId, x.OrderNo, x.SupplierId, x.Status, x.SupplierResponse,
|
||||
x.OrderDeadline, x.ExpectedArrival, x.TotalAmount, x.CurrencyId, x.IsDeleted
|
||||
FROM Prc_T_PurchaseOrder b
|
||||
INNER JOIN Prc_T_PurchaseOrderLine bl ON bl.PurchaseOrderId = b.Id AND bl.IsDeleted = 0 AND bl.MaterialRequestItemId IS NOT NULL
|
||||
INNER JOIN Prc_T_MaterialRequestItem bi ON bi.Id = bl.MaterialRequestItemId
|
||||
INNER JOIN Prc_T_MaterialRequestItem xi ON xi.MaterialRequestId = bi.MaterialRequestId
|
||||
INNER JOIN Prc_T_PurchaseOrderLine xl ON xl.MaterialRequestItemId = xi.Id AND xl.IsDeleted = 0
|
||||
INNER JOIN Prc_T_PurchaseOrder x ON x.Id = xl.PurchaseOrderId AND x.Id <> b.Id
|
||||
WHERE b.IsDeleted = 0
|
||||
15
configs/seeds/sql/object/Prc_V_PurchaseRfqAlternative.sql
Normal file
15
configs/seeds/sql/object/Prc_V_PurchaseRfqAlternative.sql
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
-- Aynı ihaledeki teklif talepleri. BaseId açık belgedir: teklif talebinde ihalenin diğer belgeleri,
|
||||
-- satınalma siparişinde kaynak teklifin ihalesindeki bütün belgeler.
|
||||
CREATE OR ALTER VIEW [dbo].[Prc_V_PurchaseRfqAlternative] AS
|
||||
SELECT b.Id AS BaseId, x.Id, x.TenantId, x.RfqNo, x.SupplierId, x.Status, x.SupplierResponse,
|
||||
x.OrderDeadline, x.ExpectedArrival, x.UntaxedAmount, x.TotalAmount, x.CurrencyId, x.IsDeleted
|
||||
FROM Prc_T_PurchaseRfq b
|
||||
INNER JOIN Prc_T_PurchaseRfq x ON x.TenderGroupId = b.TenderGroupId AND x.Id <> b.Id
|
||||
WHERE b.IsDeleted = 0
|
||||
UNION ALL
|
||||
SELECT o.Id, x.Id, x.TenantId, x.RfqNo, x.SupplierId, x.Status, x.SupplierResponse,
|
||||
x.OrderDeadline, x.ExpectedArrival, x.UntaxedAmount, x.TotalAmount, x.CurrencyId, x.IsDeleted
|
||||
FROM Prc_T_PurchaseOrder o
|
||||
INNER JOIN Prc_T_PurchaseRfq s ON s.Id = o.PurchaseRfqId
|
||||
INNER JOIN Prc_T_PurchaseRfq x ON x.TenderGroupId = s.TenderGroupId
|
||||
WHERE o.IsDeleted = 0
|
||||
35
configs/seeds/sql/object/Prc_V_PurchaseRfqComparison.sql
Normal file
35
configs/seeds/sql/object/Prc_V_PurchaseRfqComparison.sql
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
-- İhale kalemlerinin tedarikçi bazında kıyası. BaseId ihaledeki herhangi bir belgedir; her belge aynı tabloyu görür.
|
||||
-- Fiyat kurla TL'ye çevrilir (Sas_H_Currency.Rate = 1 birimin TL karşılığı), termin ihalenin açılışından gün olarak ölçülür.
|
||||
-- Puan = Fiyat ağırlığı × en düşük fiyat / fiyat + Termin ağırlığı × en kısa termin / termin (ağırlıklar ihalenin kök belgesinden).
|
||||
-- Fiyatı girilmemiş, terminsiz, "Teklif Vermedi" ya da iptal edilmiş belgenin satırı puanlanmaz.
|
||||
CREATE OR ALTER VIEW [dbo].[Prc_V_PurchaseRfqComparison] AS
|
||||
WITH Lines AS (
|
||||
SELECT b.Id AS BaseId, l.Id, l.TenantId, COALESCE(l.TenderLineId, l.Id) AS TenderLineId, l.PurchaseRfqId,
|
||||
x.RfqNo, x.SupplierId, x.Status, x.SupplierResponse, l.ProductId, l.Description, l.Quantity, l.UomId,
|
||||
l.UnitPrice, x.CurrencyId, CAST(l.UnitPrice * ISNULL(c.Rate, 1) AS decimal(18, 4)) AS PriceTry,
|
||||
COALESCE(l.DeliveryDate, x.ExpectedArrival) AS DeliveryDate,
|
||||
CASE WHEN DATEDIFF(day, g.CreationTime, COALESCE(l.DeliveryDate, x.ExpectedArrival)) < 1 THEN 1
|
||||
ELSE DATEDIFF(day, g.CreationTime, COALESCE(l.DeliveryDate, x.ExpectedArrival)) END AS LeadDays,
|
||||
g.PriceWeight, g.DeliveryWeight, l.IsSelected, l.IsDeleted,
|
||||
CASE WHEN x.Status <> 'Cancelled' AND x.SupplierResponse <> 'NotQuoted' AND l.UnitPrice > 0
|
||||
AND COALESCE(l.DeliveryDate, x.ExpectedArrival) IS NOT NULL THEN 1 ELSE 0 END AS IsEligible
|
||||
FROM Prc_T_PurchaseRfq b
|
||||
INNER JOIN Prc_T_PurchaseRfq g ON g.Id = b.TenderGroupId
|
||||
INNER JOIN Prc_T_PurchaseRfq x ON x.TenderGroupId = b.TenderGroupId AND x.IsDeleted = 0
|
||||
INNER JOIN Prc_T_PurchaseRfqLine l ON l.PurchaseRfqId = x.Id AND l.IsDeleted = 0
|
||||
LEFT JOIN Sas_H_Currency c ON c.Id = x.CurrencyId
|
||||
WHERE b.IsDeleted = 0
|
||||
), Scored AS (
|
||||
SELECT Lines.*,
|
||||
CASE WHEN IsEligible = 1 THEN CAST(
|
||||
PriceWeight * MIN(CASE WHEN IsEligible = 1 THEN PriceTry END) OVER (PARTITION BY BaseId, TenderLineId) / PriceTry
|
||||
+ DeliveryWeight * MIN(CASE WHEN IsEligible = 1 THEN LeadDays END) OVER (PARTITION BY BaseId, TenderLineId) * 1.0 / LeadDays
|
||||
AS decimal(9, 2)) END AS Score
|
||||
FROM Lines
|
||||
)
|
||||
SELECT BaseId, Id, TenantId, TenderLineId, PurchaseRfqId, RfqNo, SupplierId, Status, SupplierResponse, ProductId, Description,
|
||||
Quantity, UomId, UnitPrice, CurrencyId, PriceTry, DeliveryDate, LeadDays, Score,
|
||||
CAST(CASE WHEN IsEligible = 1 AND ROW_NUMBER() OVER (PARTITION BY BaseId, TenderLineId
|
||||
ORDER BY IsEligible DESC, Score DESC, PriceTry, LeadDays) = 1 THEN 1 ELSE 0 END AS bit) AS IsRecommended,
|
||||
IsSelected, IsDeleted
|
||||
FROM Scored
|
||||
|
|
@ -2138,7 +2138,7 @@
|
|||
"EditOrderNo": 8,
|
||||
"EditGroupOrderNo": 1,
|
||||
"EditorType2": "dxTextBox",
|
||||
"ColSpan": 2,
|
||||
"ColSpan": 4,
|
||||
"EditorOptions": "{\"autoResizeEnabled\":true,\"minHeight\":60}",
|
||||
"GridBoxOptions": null,
|
||||
"TagBoxOptions": null,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -3,7 +3,7 @@
|
|||
"ComponentKind": 0,
|
||||
"WizardName": "Prc_PurchaseOrderAlternative",
|
||||
"WizardCode": "App.Prc.PurchaseOrderAlternative",
|
||||
"SeededAt": "2026-10-11T01:00:01.6595742+03:00",
|
||||
"SeededAt": "2026-10-11T21:09:00+03:00",
|
||||
"CustomComponentName": null,
|
||||
"PermissionGroupName": "App.Prc",
|
||||
"ModuleId": "Prc",
|
||||
|
|
@ -29,34 +29,12 @@
|
|||
"MenuParentTr": "Siparişler",
|
||||
"PermissionGroupEn": "Purchasing",
|
||||
"PermissionGroupTr": "Satınalma",
|
||||
"MenuEn": "Alternative Quotes",
|
||||
"MenuTr": "Teklifler",
|
||||
"TitleEn": "Alternative Quotes",
|
||||
"TitleTr": "Teklifler",
|
||||
"DescEn": "Alternative Quotes — other RFQs and purchase orders that carry lines of the same material requests as the open document.\nWhere: Purchasing › Orders › Requests for Quotation and Purchase Orders › Quotes tab (no menu of its own, read-only).\nFields: reference, supplier, supplier response, order deadline, expected arrival, total, currency, status.\nUsage: compare the quotes collected from different suppliers for the same request before confirming one of them.",
|
||||
"DescTr": "Teklifler — açık belgeyle aynı malzeme talebinin kalemlerini taşıyan diğer teklif talepleri ve siparişler.\nNerede: Satınalma › Siparişler › Teklif Talepleri ve Satınalma Siparişleri › Teklifler sekmesi (kendi menüsü yoktur, salt okunur).\nAlanlar: referans, tedarikçi, tedarikçi yanıtı, sipariş zaman sınırı, beklenen geliş, toplam, para birimi, durum.\nKullanım: aynı talep için farklı tedarikçilerden toplanan teklifler, birini onaylamadan önce burada karşılaştırılır.",
|
||||
"Texts": [
|
||||
{
|
||||
"Key": "App.Prc.OrderStatus.Draft",
|
||||
"En": "RFQ",
|
||||
"Tr": "Teklif Talebi"
|
||||
},
|
||||
{
|
||||
"Key": "App.Prc.OrderStatus.Sent",
|
||||
"En": "RFQ Sent",
|
||||
"Tr": "Teklif Talebi Gönderildi"
|
||||
},
|
||||
{
|
||||
"Key": "App.Prc.OrderStatus.Purchase",
|
||||
"En": "Purchase Order",
|
||||
"Tr": "Satınalma Siparişi"
|
||||
},
|
||||
{
|
||||
"Key": "App.Prc.OrderStatus.Cancelled",
|
||||
"En": "Cancelled",
|
||||
"Tr": "İptal Edildi"
|
||||
}
|
||||
]
|
||||
"MenuEn": "Source Quotes",
|
||||
"MenuTr": "Kaynak Teklifler",
|
||||
"TitleEn": "Source Quotes",
|
||||
"TitleTr": "Kaynak Teklifler",
|
||||
"DescEn": "Source Quotes — the requests for quotation of the tender the purchase order was converted from.\nWhere: Purchasing › Orders › Purchase Orders › Quotes tab (no menu of its own, read-only; empty for orders written without an RFQ).\nFields: RFQ no, supplier, status, supplier response, order deadline, expected arrival, untaxed amount, total, currency.\nUsage: see which suppliers were asked and which documents were converted or cancelled in the tender.",
|
||||
"DescTr": "Kaynak Teklifler — satınalma siparişinin dönüştürüldüğü ihalenin teklif talepleri.\nNerede: Satınalma › Siparişler › Satınalma Siparişleri › Teklifler sekmesi (kendi menüsü yoktur, salt okunur; teklifsiz yazılan siparişte boştur).\nAlanlar: teklif talep no, tedarikçi, durum, tedarikçi yanıtı, sipariş zaman sınırı, beklenen geliş, vergi hariç tutar, toplam, para birimi.\nKullanım: ihalede hangi tedarikçilere sorulduğu, hangi belgenin siparişe dönüştüğü ve hangilerinin iptal edildiği görülür."
|
||||
},
|
||||
"Groups": [
|
||||
{
|
||||
|
|
@ -68,16 +46,16 @@
|
|||
"Tr": "Kimlik"
|
||||
},
|
||||
{
|
||||
"FieldName": "BaseOrderId",
|
||||
"CaptionName": "App.Listform.ListformField.BaseOrderId",
|
||||
"FieldName": "BaseId",
|
||||
"CaptionName": "App.Listform.ListformField.BaseId",
|
||||
"En": "Base Document",
|
||||
"Tr": "Ana Belge"
|
||||
},
|
||||
{
|
||||
"FieldName": "OrderNo",
|
||||
"CaptionName": "App.Listform.ListformField.OrderNo",
|
||||
"En": "Reference",
|
||||
"Tr": "Referans"
|
||||
"FieldName": "RfqNo",
|
||||
"CaptionName": "App.Listform.ListformField.RfqNo",
|
||||
"En": "RFQ No",
|
||||
"Tr": "Teklif Talep No"
|
||||
},
|
||||
{
|
||||
"FieldName": "SupplierId",
|
||||
|
|
@ -85,6 +63,12 @@
|
|||
"En": "Supplier",
|
||||
"Tr": "Tedarikçi"
|
||||
},
|
||||
{
|
||||
"FieldName": "Status",
|
||||
"CaptionName": "App.Listform.ListformField.Status",
|
||||
"En": "Status",
|
||||
"Tr": "Durum"
|
||||
},
|
||||
{
|
||||
"FieldName": "SupplierResponse",
|
||||
"CaptionName": "App.Listform.ListformField.SupplierResponse",
|
||||
|
|
@ -103,23 +87,23 @@
|
|||
"En": "Expected Arrival",
|
||||
"Tr": "Beklenen Geliş"
|
||||
},
|
||||
{
|
||||
"FieldName": "UntaxedAmount",
|
||||
"CaptionName": "App.Listform.ListformField.UntaxedAmount",
|
||||
"En": "Untaxed Amount",
|
||||
"Tr": "Vergi Hariç Tutar"
|
||||
},
|
||||
{
|
||||
"FieldName": "TotalAmount",
|
||||
"CaptionName": "App.Listform.ListformField.TotalAmount",
|
||||
"En": "Total",
|
||||
"Tr": "Toplam"
|
||||
"En": "Total Amount",
|
||||
"Tr": "Toplam Tutar"
|
||||
},
|
||||
{
|
||||
"FieldName": "CurrencyId",
|
||||
"CaptionName": "App.Listform.ListformField.CurrencyId",
|
||||
"En": "Currency",
|
||||
"Tr": "Para Birimi"
|
||||
},
|
||||
{
|
||||
"FieldName": "Status",
|
||||
"CaptionName": "App.Listform.ListformField.Status",
|
||||
"En": "Status",
|
||||
"Tr": "Durumu"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -130,8 +114,8 @@
|
|||
"DataSourceCode": "Default",
|
||||
"KeyFieldDbSourceType": 9,
|
||||
"TableName": null,
|
||||
"DefaultFilter": null,
|
||||
"SelectCommand": "Prc_V_PurchaseOrderAlternative",
|
||||
"DefaultFilter": "\"IsDeleted\" = 'false'",
|
||||
"SelectCommand": "Prc_V_PurchaseRfqAlternative",
|
||||
"SelectCommandType": 2,
|
||||
"SelectFieldsDefaultValueDto": [],
|
||||
"SeedFilePath": null,
|
||||
|
|
@ -787,7 +771,7 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": null,
|
||||
"EditGroupOrderNo": null,
|
||||
|
|
@ -820,11 +804,11 @@
|
|||
"JoinFieldName2": null,
|
||||
"BaseTableJoinFieldName2_OrValue": null
|
||||
},
|
||||
"FieldName": "BaseOrderId",
|
||||
"CaptionName": "App.Listform.ListformField.BaseOrderId",
|
||||
"FieldName": "BaseId",
|
||||
"CaptionName": "App.Listform.ListformField.BaseId",
|
||||
"PlaceHolder": null,
|
||||
"ReadOnly": false,
|
||||
"Visible": true,
|
||||
"Visible": false,
|
||||
"IsActive": true,
|
||||
"Width": 0,
|
||||
"ListOrderNo": 2,
|
||||
|
|
@ -913,7 +897,7 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": null,
|
||||
"EditGroupOrderNo": null,
|
||||
|
|
@ -946,8 +930,8 @@
|
|||
"JoinFieldName2": null,
|
||||
"BaseTableJoinFieldName2_OrValue": null
|
||||
},
|
||||
"FieldName": "OrderNo",
|
||||
"CaptionName": "App.Listform.ListformField.OrderNo",
|
||||
"FieldName": "RfqNo",
|
||||
"CaptionName": "App.Listform.ListformField.RfqNo",
|
||||
"PlaceHolder": null,
|
||||
"ReadOnly": false,
|
||||
"Visible": true,
|
||||
|
|
@ -1039,13 +1023,13 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": null,
|
||||
"EditGroupOrderNo": null,
|
||||
"EditorType2": "dxTextBox",
|
||||
"ColSpan": 1,
|
||||
"EditorOptions": null,
|
||||
"EditorOptions": "{\"readOnly\":true}",
|
||||
"GridBoxOptions": null,
|
||||
"TagBoxOptions": null,
|
||||
"ImageUploadOptions": null,
|
||||
|
|
@ -1137,7 +1121,7 @@
|
|||
"CascadeFilterOperator": "=",
|
||||
"CascadeParentFields": null,
|
||||
"CascadeEmptyFields": null,
|
||||
"LookupQuery": "SELECT Id AS [Key], Name AS [Name] FROM Adm_T_Contact WHERE TenantId = '@TENANTID'"
|
||||
"LookupQuery": "SELECT Id AS [Key], Name AS [Name] FROM Adm_T_Contact WHERE TenantId = '@TENANTID' ORDER BY Name"
|
||||
},
|
||||
"ValidationRuleDto": [],
|
||||
"ColumnStylingDto": [],
|
||||
|
|
@ -1165,13 +1149,139 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": null,
|
||||
"EditGroupOrderNo": null,
|
||||
"EditorType2": "dxSelectBox",
|
||||
"ColSpan": 1,
|
||||
"EditorOptions": null,
|
||||
"EditorOptions": "{\"showClearButton\":true,\"searchEnabled\":true}",
|
||||
"GridBoxOptions": null,
|
||||
"TagBoxOptions": null,
|
||||
"ImageUploadOptions": null,
|
||||
"EditorScript": null,
|
||||
"LastModificationTime": null,
|
||||
"LastModifierId": null,
|
||||
"CreationTime": "0001-01-01T00:00:00",
|
||||
"CreatorId": null,
|
||||
"Id": "00000000-0000-0000-0000-000000000000"
|
||||
},
|
||||
{
|
||||
"EditType": null,
|
||||
"ListFormCode": "App.Prc.PurchaseOrderAlternative",
|
||||
"RoleId": null,
|
||||
"UserId": null,
|
||||
"ColumnJoinTableDto": {
|
||||
"JoinType": null,
|
||||
"TableName": null,
|
||||
"JoinFieldName": null,
|
||||
"BaseTableJoinFieldName": null,
|
||||
"SelectFieldName": null,
|
||||
"FieldNameAlias": null,
|
||||
"JoinCondition2": "AND",
|
||||
"JoinFieldName2": null,
|
||||
"BaseTableJoinFieldName2_OrValue": null
|
||||
},
|
||||
"FieldName": "Status",
|
||||
"CaptionName": "App.Listform.ListformField.Status",
|
||||
"PlaceHolder": null,
|
||||
"ReadOnly": false,
|
||||
"Visible": true,
|
||||
"IsActive": true,
|
||||
"Width": 0,
|
||||
"ListOrderNo": 5,
|
||||
"SourceDbType": 16,
|
||||
"CultureName": "en",
|
||||
"DataType": "string",
|
||||
"SortIndex": 0,
|
||||
"SortDirection": null,
|
||||
"AllowSearch": true,
|
||||
"AllowEditing": true,
|
||||
"AllowAdding": true,
|
||||
"ColumnCssClass": null,
|
||||
"ColumnCssValue": null,
|
||||
"BandName": null,
|
||||
"ColumnFilterDto": {
|
||||
"AllowFiltering": true,
|
||||
"FilterOperations": null,
|
||||
"SelectedFilterOperation": null,
|
||||
"FilterValue": null
|
||||
},
|
||||
"ColumnHeaderDto": {
|
||||
"AllowHeaderFiltering": true,
|
||||
"AllowSearch": false,
|
||||
"DataSource": null,
|
||||
"DataSourceString": ""
|
||||
},
|
||||
"ColumnGroupingDto": {
|
||||
"AllowGrouping": true,
|
||||
"GroupIndex": null,
|
||||
"AutoExpandGroup": false
|
||||
},
|
||||
"ColumnCustomizationDto": {
|
||||
"Fixed": false,
|
||||
"FixedPosition": "left",
|
||||
"AllowReordering": true
|
||||
},
|
||||
"ColumnTotalSummaryDto": {
|
||||
"SummaryType": null,
|
||||
"ValueFormat": null,
|
||||
"ShowInGroupFooter": false,
|
||||
"AlignByColumn": false,
|
||||
"DisplayFormat": null,
|
||||
"ShowInColumn": null
|
||||
},
|
||||
"ColumnGroupSummaryDto": {
|
||||
"SummaryType": null,
|
||||
"ValueFormat": null,
|
||||
"ShowInGroupFooter": false,
|
||||
"AlignByColumn": false,
|
||||
"DisplayFormat": null,
|
||||
"ShowInColumn": null
|
||||
},
|
||||
"LookupDto": {
|
||||
"DataSourceType": 1,
|
||||
"ValueExpr": "key",
|
||||
"DisplayExpr": "name",
|
||||
"CascadeRelationField": null,
|
||||
"CascadeFilterOperator": "=",
|
||||
"CascadeParentFields": null,
|
||||
"CascadeEmptyFields": null,
|
||||
"LookupQuery": "[{\"key\":\"Draft\",\"name\":\"App.Prc.OrderStatus.Draft\"},{\"key\":\"Sent\",\"name\":\"App.Prc.OrderStatus.Sent\"},{\"key\":\"Purchase\",\"name\":\"App.Prc.OrderStatus.Purchase\"},{\"key\":\"Cancelled\",\"name\":\"App.Prc.OrderStatus.Cancelled\"}]"
|
||||
},
|
||||
"ValidationRuleDto": [],
|
||||
"ColumnStylingDto": [],
|
||||
"PermissionDto": {
|
||||
"Deny": false,
|
||||
"C": "App.Prc.PurchaseOrderAlternative.Create",
|
||||
"R": "App.Prc.PurchaseOrderAlternative",
|
||||
"U": "App.Prc.PurchaseOrderAlternative.Update",
|
||||
"E": true,
|
||||
"I": true
|
||||
},
|
||||
"CanRead": false,
|
||||
"CanCreate": false,
|
||||
"CanUpdate": false,
|
||||
"CanExport": false,
|
||||
"DefaultValue": null,
|
||||
"DefaultValueType": 0,
|
||||
"PivotSettingsDto": {
|
||||
"IsPivot": true,
|
||||
"Expanded": false,
|
||||
"SortOrder": "asc",
|
||||
"Area": "filter",
|
||||
"Format": null,
|
||||
"SummaryType": null,
|
||||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": null,
|
||||
"EditGroupOrderNo": null,
|
||||
"EditorType2": "dxSelectBox",
|
||||
"ColSpan": 1,
|
||||
"EditorOptions": "{\"readOnly\":true}",
|
||||
"GridBoxOptions": null,
|
||||
"TagBoxOptions": null,
|
||||
"ImageUploadOptions": null,
|
||||
|
|
@ -1205,7 +1315,7 @@
|
|||
"Visible": true,
|
||||
"IsActive": true,
|
||||
"Width": 0,
|
||||
"ListOrderNo": 5,
|
||||
"ListOrderNo": 6,
|
||||
"SourceDbType": 16,
|
||||
"CultureName": "en",
|
||||
"DataType": "string",
|
||||
|
|
@ -1291,7 +1401,7 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": null,
|
||||
"EditGroupOrderNo": null,
|
||||
|
|
@ -1331,132 +1441,6 @@
|
|||
"Visible": true,
|
||||
"IsActive": true,
|
||||
"Width": 0,
|
||||
"ListOrderNo": 6,
|
||||
"SourceDbType": 6,
|
||||
"CultureName": "en",
|
||||
"DataType": "datetime",
|
||||
"SortIndex": 0,
|
||||
"SortDirection": null,
|
||||
"AllowSearch": true,
|
||||
"AllowEditing": true,
|
||||
"AllowAdding": true,
|
||||
"ColumnCssClass": null,
|
||||
"ColumnCssValue": null,
|
||||
"BandName": null,
|
||||
"ColumnFilterDto": {
|
||||
"AllowFiltering": true,
|
||||
"FilterOperations": null,
|
||||
"SelectedFilterOperation": null,
|
||||
"FilterValue": null
|
||||
},
|
||||
"ColumnHeaderDto": {
|
||||
"AllowHeaderFiltering": true,
|
||||
"AllowSearch": false,
|
||||
"DataSource": null,
|
||||
"DataSourceString": ""
|
||||
},
|
||||
"ColumnGroupingDto": {
|
||||
"AllowGrouping": true,
|
||||
"GroupIndex": null,
|
||||
"AutoExpandGroup": false
|
||||
},
|
||||
"ColumnCustomizationDto": {
|
||||
"Fixed": false,
|
||||
"FixedPosition": "left",
|
||||
"AllowReordering": true
|
||||
},
|
||||
"ColumnTotalSummaryDto": {
|
||||
"SummaryType": null,
|
||||
"ValueFormat": null,
|
||||
"ShowInGroupFooter": false,
|
||||
"AlignByColumn": false,
|
||||
"DisplayFormat": null,
|
||||
"ShowInColumn": null
|
||||
},
|
||||
"ColumnGroupSummaryDto": {
|
||||
"SummaryType": null,
|
||||
"ValueFormat": null,
|
||||
"ShowInGroupFooter": false,
|
||||
"AlignByColumn": false,
|
||||
"DisplayFormat": null,
|
||||
"ShowInColumn": null
|
||||
},
|
||||
"LookupDto": {
|
||||
"DataSourceType": 0,
|
||||
"ValueExpr": "Key",
|
||||
"DisplayExpr": "Name",
|
||||
"CascadeRelationField": null,
|
||||
"CascadeFilterOperator": "=",
|
||||
"CascadeParentFields": null,
|
||||
"CascadeEmptyFields": null,
|
||||
"LookupQuery": null
|
||||
},
|
||||
"ValidationRuleDto": [],
|
||||
"ColumnStylingDto": [],
|
||||
"PermissionDto": {
|
||||
"Deny": false,
|
||||
"C": "App.Prc.PurchaseOrderAlternative.Create",
|
||||
"R": "App.Prc.PurchaseOrderAlternative",
|
||||
"U": "App.Prc.PurchaseOrderAlternative.Update",
|
||||
"E": true,
|
||||
"I": true
|
||||
},
|
||||
"CanRead": false,
|
||||
"CanCreate": false,
|
||||
"CanUpdate": false,
|
||||
"CanExport": false,
|
||||
"DefaultValue": null,
|
||||
"DefaultValueType": 0,
|
||||
"PivotSettingsDto": {
|
||||
"IsPivot": true,
|
||||
"Expanded": false,
|
||||
"SortOrder": "asc",
|
||||
"Area": "filter",
|
||||
"Format": null,
|
||||
"SummaryType": null,
|
||||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Format": null,
|
||||
"EditOrderNo": null,
|
||||
"EditGroupOrderNo": null,
|
||||
"EditorType2": "dxDateBox",
|
||||
"ColSpan": 1,
|
||||
"EditorOptions": null,
|
||||
"GridBoxOptions": null,
|
||||
"TagBoxOptions": null,
|
||||
"ImageUploadOptions": null,
|
||||
"EditorScript": null,
|
||||
"LastModificationTime": null,
|
||||
"LastModifierId": null,
|
||||
"CreationTime": "0001-01-01T00:00:00",
|
||||
"CreatorId": null,
|
||||
"Id": "00000000-0000-0000-0000-000000000000"
|
||||
},
|
||||
{
|
||||
"EditType": null,
|
||||
"ListFormCode": "App.Prc.PurchaseOrderAlternative",
|
||||
"RoleId": null,
|
||||
"UserId": null,
|
||||
"ColumnJoinTableDto": {
|
||||
"JoinType": null,
|
||||
"TableName": null,
|
||||
"JoinFieldName": null,
|
||||
"BaseTableJoinFieldName": null,
|
||||
"SelectFieldName": null,
|
||||
"FieldNameAlias": null,
|
||||
"JoinCondition2": "AND",
|
||||
"JoinFieldName2": null,
|
||||
"BaseTableJoinFieldName2_OrValue": null
|
||||
},
|
||||
"FieldName": "ExpectedArrival",
|
||||
"CaptionName": "App.Listform.ListformField.ExpectedArrival",
|
||||
"PlaceHolder": null,
|
||||
"ReadOnly": false,
|
||||
"Visible": true,
|
||||
"IsActive": true,
|
||||
"Width": 0,
|
||||
"ListOrderNo": 7,
|
||||
"SourceDbType": 6,
|
||||
"CultureName": "en",
|
||||
|
|
@ -1543,13 +1527,13 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": null,
|
||||
"EditGroupOrderNo": null,
|
||||
"EditorType2": "dxDateBox",
|
||||
"ColSpan": 1,
|
||||
"EditorOptions": null,
|
||||
"EditorOptions": "{\"type\":\"datetime\",\"displayFormat\":\"dd.MM.yyyy HH:mm\",\"useMaskBehavior\":true,\"showClearButton\":true}",
|
||||
"GridBoxOptions": null,
|
||||
"TagBoxOptions": null,
|
||||
"ImageUploadOptions": null,
|
||||
|
|
@ -1576,14 +1560,140 @@
|
|||
"JoinFieldName2": null,
|
||||
"BaseTableJoinFieldName2_OrValue": null
|
||||
},
|
||||
"FieldName": "TotalAmount",
|
||||
"CaptionName": "App.Listform.ListformField.TotalAmount",
|
||||
"FieldName": "ExpectedArrival",
|
||||
"CaptionName": "App.Listform.ListformField.ExpectedArrival",
|
||||
"PlaceHolder": null,
|
||||
"ReadOnly": false,
|
||||
"Visible": true,
|
||||
"IsActive": true,
|
||||
"Width": 0,
|
||||
"ListOrderNo": 8,
|
||||
"SourceDbType": 6,
|
||||
"CultureName": "en",
|
||||
"DataType": "datetime",
|
||||
"SortIndex": 0,
|
||||
"SortDirection": null,
|
||||
"AllowSearch": true,
|
||||
"AllowEditing": true,
|
||||
"AllowAdding": true,
|
||||
"ColumnCssClass": null,
|
||||
"ColumnCssValue": null,
|
||||
"BandName": null,
|
||||
"ColumnFilterDto": {
|
||||
"AllowFiltering": true,
|
||||
"FilterOperations": null,
|
||||
"SelectedFilterOperation": null,
|
||||
"FilterValue": null
|
||||
},
|
||||
"ColumnHeaderDto": {
|
||||
"AllowHeaderFiltering": true,
|
||||
"AllowSearch": false,
|
||||
"DataSource": null,
|
||||
"DataSourceString": ""
|
||||
},
|
||||
"ColumnGroupingDto": {
|
||||
"AllowGrouping": true,
|
||||
"GroupIndex": null,
|
||||
"AutoExpandGroup": false
|
||||
},
|
||||
"ColumnCustomizationDto": {
|
||||
"Fixed": false,
|
||||
"FixedPosition": "left",
|
||||
"AllowReordering": true
|
||||
},
|
||||
"ColumnTotalSummaryDto": {
|
||||
"SummaryType": null,
|
||||
"ValueFormat": null,
|
||||
"ShowInGroupFooter": false,
|
||||
"AlignByColumn": false,
|
||||
"DisplayFormat": null,
|
||||
"ShowInColumn": null
|
||||
},
|
||||
"ColumnGroupSummaryDto": {
|
||||
"SummaryType": null,
|
||||
"ValueFormat": null,
|
||||
"ShowInGroupFooter": false,
|
||||
"AlignByColumn": false,
|
||||
"DisplayFormat": null,
|
||||
"ShowInColumn": null
|
||||
},
|
||||
"LookupDto": {
|
||||
"DataSourceType": 0,
|
||||
"ValueExpr": "Key",
|
||||
"DisplayExpr": "Name",
|
||||
"CascadeRelationField": null,
|
||||
"CascadeFilterOperator": "=",
|
||||
"CascadeParentFields": null,
|
||||
"CascadeEmptyFields": null,
|
||||
"LookupQuery": null
|
||||
},
|
||||
"ValidationRuleDto": [],
|
||||
"ColumnStylingDto": [],
|
||||
"PermissionDto": {
|
||||
"Deny": false,
|
||||
"C": "App.Prc.PurchaseOrderAlternative.Create",
|
||||
"R": "App.Prc.PurchaseOrderAlternative",
|
||||
"U": "App.Prc.PurchaseOrderAlternative.Update",
|
||||
"E": true,
|
||||
"I": true
|
||||
},
|
||||
"CanRead": false,
|
||||
"CanCreate": false,
|
||||
"CanUpdate": false,
|
||||
"CanExport": false,
|
||||
"DefaultValue": null,
|
||||
"DefaultValueType": 0,
|
||||
"PivotSettingsDto": {
|
||||
"IsPivot": true,
|
||||
"Expanded": false,
|
||||
"SortOrder": "asc",
|
||||
"Area": "filter",
|
||||
"Format": null,
|
||||
"SummaryType": null,
|
||||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": null,
|
||||
"EditGroupOrderNo": null,
|
||||
"EditorType2": "dxDateBox",
|
||||
"ColSpan": 1,
|
||||
"EditorOptions": "{\"type\":\"datetime\",\"displayFormat\":\"dd.MM.yyyy HH:mm\",\"useMaskBehavior\":true,\"showClearButton\":true}",
|
||||
"GridBoxOptions": null,
|
||||
"TagBoxOptions": null,
|
||||
"ImageUploadOptions": null,
|
||||
"EditorScript": null,
|
||||
"LastModificationTime": null,
|
||||
"LastModifierId": null,
|
||||
"CreationTime": "0001-01-01T00:00:00",
|
||||
"CreatorId": null,
|
||||
"Id": "00000000-0000-0000-0000-000000000000"
|
||||
},
|
||||
{
|
||||
"EditType": null,
|
||||
"ListFormCode": "App.Prc.PurchaseOrderAlternative",
|
||||
"RoleId": null,
|
||||
"UserId": null,
|
||||
"ColumnJoinTableDto": {
|
||||
"JoinType": null,
|
||||
"TableName": null,
|
||||
"JoinFieldName": null,
|
||||
"BaseTableJoinFieldName": null,
|
||||
"SelectFieldName": null,
|
||||
"FieldNameAlias": null,
|
||||
"JoinCondition2": "AND",
|
||||
"JoinFieldName2": null,
|
||||
"BaseTableJoinFieldName2_OrValue": null
|
||||
},
|
||||
"FieldName": "UntaxedAmount",
|
||||
"CaptionName": "App.Listform.ListformField.UntaxedAmount",
|
||||
"PlaceHolder": null,
|
||||
"ReadOnly": false,
|
||||
"Visible": true,
|
||||
"IsActive": true,
|
||||
"Width": 0,
|
||||
"ListOrderNo": 9,
|
||||
"SourceDbType": 7,
|
||||
"CultureName": "en",
|
||||
"DataType": "number",
|
||||
|
|
@ -1669,13 +1779,139 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": null,
|
||||
"EditGroupOrderNo": null,
|
||||
"EditorType2": "dxNumberBox",
|
||||
"ColSpan": 1,
|
||||
"EditorOptions": "{\"format\":\"#,##0.00\"}",
|
||||
"EditorOptions": "{\"readOnly\":true,\"format\":\"#,##0.00\"}",
|
||||
"GridBoxOptions": null,
|
||||
"TagBoxOptions": null,
|
||||
"ImageUploadOptions": null,
|
||||
"EditorScript": null,
|
||||
"LastModificationTime": null,
|
||||
"LastModifierId": null,
|
||||
"CreationTime": "0001-01-01T00:00:00",
|
||||
"CreatorId": null,
|
||||
"Id": "00000000-0000-0000-0000-000000000000"
|
||||
},
|
||||
{
|
||||
"EditType": null,
|
||||
"ListFormCode": "App.Prc.PurchaseOrderAlternative",
|
||||
"RoleId": null,
|
||||
"UserId": null,
|
||||
"ColumnJoinTableDto": {
|
||||
"JoinType": null,
|
||||
"TableName": null,
|
||||
"JoinFieldName": null,
|
||||
"BaseTableJoinFieldName": null,
|
||||
"SelectFieldName": null,
|
||||
"FieldNameAlias": null,
|
||||
"JoinCondition2": "AND",
|
||||
"JoinFieldName2": null,
|
||||
"BaseTableJoinFieldName2_OrValue": null
|
||||
},
|
||||
"FieldName": "TotalAmount",
|
||||
"CaptionName": "App.Listform.ListformField.TotalAmount",
|
||||
"PlaceHolder": null,
|
||||
"ReadOnly": false,
|
||||
"Visible": true,
|
||||
"IsActive": true,
|
||||
"Width": 0,
|
||||
"ListOrderNo": 10,
|
||||
"SourceDbType": 7,
|
||||
"CultureName": "en",
|
||||
"DataType": "number",
|
||||
"SortIndex": 0,
|
||||
"SortDirection": null,
|
||||
"AllowSearch": true,
|
||||
"AllowEditing": true,
|
||||
"AllowAdding": true,
|
||||
"ColumnCssClass": null,
|
||||
"ColumnCssValue": null,
|
||||
"BandName": null,
|
||||
"ColumnFilterDto": {
|
||||
"AllowFiltering": true,
|
||||
"FilterOperations": null,
|
||||
"SelectedFilterOperation": null,
|
||||
"FilterValue": null
|
||||
},
|
||||
"ColumnHeaderDto": {
|
||||
"AllowHeaderFiltering": true,
|
||||
"AllowSearch": false,
|
||||
"DataSource": null,
|
||||
"DataSourceString": ""
|
||||
},
|
||||
"ColumnGroupingDto": {
|
||||
"AllowGrouping": true,
|
||||
"GroupIndex": null,
|
||||
"AutoExpandGroup": false
|
||||
},
|
||||
"ColumnCustomizationDto": {
|
||||
"Fixed": false,
|
||||
"FixedPosition": "left",
|
||||
"AllowReordering": true
|
||||
},
|
||||
"ColumnTotalSummaryDto": {
|
||||
"SummaryType": "sum",
|
||||
"ValueFormat": "#,##0.00",
|
||||
"ShowInGroupFooter": false,
|
||||
"AlignByColumn": false,
|
||||
"DisplayFormat": "{0}",
|
||||
"ShowInColumn": null
|
||||
},
|
||||
"ColumnGroupSummaryDto": {
|
||||
"SummaryType": null,
|
||||
"ValueFormat": null,
|
||||
"ShowInGroupFooter": false,
|
||||
"AlignByColumn": false,
|
||||
"DisplayFormat": null,
|
||||
"ShowInColumn": null
|
||||
},
|
||||
"LookupDto": {
|
||||
"DataSourceType": 0,
|
||||
"ValueExpr": "Key",
|
||||
"DisplayExpr": "Name",
|
||||
"CascadeRelationField": null,
|
||||
"CascadeFilterOperator": "=",
|
||||
"CascadeParentFields": null,
|
||||
"CascadeEmptyFields": null,
|
||||
"LookupQuery": null
|
||||
},
|
||||
"ValidationRuleDto": [],
|
||||
"ColumnStylingDto": [],
|
||||
"PermissionDto": {
|
||||
"Deny": false,
|
||||
"C": "App.Prc.PurchaseOrderAlternative.Create",
|
||||
"R": "App.Prc.PurchaseOrderAlternative",
|
||||
"U": "App.Prc.PurchaseOrderAlternative.Update",
|
||||
"E": true,
|
||||
"I": true
|
||||
},
|
||||
"CanRead": false,
|
||||
"CanCreate": false,
|
||||
"CanUpdate": false,
|
||||
"CanExport": false,
|
||||
"DefaultValue": null,
|
||||
"DefaultValueType": 0,
|
||||
"PivotSettingsDto": {
|
||||
"IsPivot": true,
|
||||
"Expanded": false,
|
||||
"SortOrder": "asc",
|
||||
"Area": "filter",
|
||||
"Format": null,
|
||||
"SummaryType": null,
|
||||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": null,
|
||||
"EditGroupOrderNo": null,
|
||||
"EditorType2": "dxNumberBox",
|
||||
"ColSpan": 1,
|
||||
"EditorOptions": "{\"readOnly\":true,\"format\":\"#,##0.00\"}",
|
||||
"GridBoxOptions": null,
|
||||
"TagBoxOptions": null,
|
||||
"ImageUploadOptions": null,
|
||||
|
|
@ -1709,7 +1945,7 @@
|
|||
"Visible": true,
|
||||
"IsActive": true,
|
||||
"Width": 0,
|
||||
"ListOrderNo": 9,
|
||||
"ListOrderNo": 11,
|
||||
"SourceDbType": 16,
|
||||
"CultureName": "en",
|
||||
"DataType": "string",
|
||||
|
|
@ -1795,7 +2031,7 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": null,
|
||||
"EditGroupOrderNo": null,
|
||||
|
|
@ -1811,149 +2047,17 @@
|
|||
"CreationTime": "0001-01-01T00:00:00",
|
||||
"CreatorId": null,
|
||||
"Id": "00000000-0000-0000-0000-000000000000"
|
||||
},
|
||||
{
|
||||
"EditType": null,
|
||||
"ListFormCode": "App.Prc.PurchaseOrderAlternative",
|
||||
"RoleId": null,
|
||||
"UserId": null,
|
||||
"ColumnJoinTableDto": {
|
||||
"JoinType": null,
|
||||
"TableName": null,
|
||||
"JoinFieldName": null,
|
||||
"BaseTableJoinFieldName": null,
|
||||
"SelectFieldName": null,
|
||||
"FieldNameAlias": null,
|
||||
"JoinCondition2": "AND",
|
||||
"JoinFieldName2": null,
|
||||
"BaseTableJoinFieldName2_OrValue": null
|
||||
},
|
||||
"FieldName": "Status",
|
||||
"CaptionName": "App.Listform.ListformField.Status",
|
||||
"PlaceHolder": null,
|
||||
"ReadOnly": false,
|
||||
"Visible": true,
|
||||
"IsActive": true,
|
||||
"Width": 0,
|
||||
"ListOrderNo": 10,
|
||||
"SourceDbType": 16,
|
||||
"CultureName": "en",
|
||||
"DataType": "string",
|
||||
"SortIndex": 0,
|
||||
"SortDirection": null,
|
||||
"AllowSearch": true,
|
||||
"AllowEditing": true,
|
||||
"AllowAdding": true,
|
||||
"ColumnCssClass": null,
|
||||
"ColumnCssValue": null,
|
||||
"BandName": null,
|
||||
"ColumnFilterDto": {
|
||||
"AllowFiltering": true,
|
||||
"FilterOperations": null,
|
||||
"SelectedFilterOperation": null,
|
||||
"FilterValue": null
|
||||
},
|
||||
"ColumnHeaderDto": {
|
||||
"AllowHeaderFiltering": true,
|
||||
"AllowSearch": false,
|
||||
"DataSource": null,
|
||||
"DataSourceString": ""
|
||||
},
|
||||
"ColumnGroupingDto": {
|
||||
"AllowGrouping": true,
|
||||
"GroupIndex": null,
|
||||
"AutoExpandGroup": false
|
||||
},
|
||||
"ColumnCustomizationDto": {
|
||||
"Fixed": false,
|
||||
"FixedPosition": "left",
|
||||
"AllowReordering": true
|
||||
},
|
||||
"ColumnTotalSummaryDto": {
|
||||
"SummaryType": null,
|
||||
"ValueFormat": null,
|
||||
"ShowInGroupFooter": false,
|
||||
"AlignByColumn": false,
|
||||
"DisplayFormat": null,
|
||||
"ShowInColumn": null
|
||||
},
|
||||
"ColumnGroupSummaryDto": {
|
||||
"SummaryType": null,
|
||||
"ValueFormat": null,
|
||||
"ShowInGroupFooter": false,
|
||||
"AlignByColumn": false,
|
||||
"DisplayFormat": null,
|
||||
"ShowInColumn": null
|
||||
},
|
||||
"LookupDto": {
|
||||
"DataSourceType": 1,
|
||||
"ValueExpr": "key",
|
||||
"DisplayExpr": "name",
|
||||
"CascadeRelationField": null,
|
||||
"CascadeFilterOperator": "=",
|
||||
"CascadeParentFields": null,
|
||||
"CascadeEmptyFields": null,
|
||||
"LookupQuery": "[{\"key\":\"Draft\",\"name\":\"App.Prc.OrderStatus.Draft\"},{\"key\":\"Sent\",\"name\":\"App.Prc.OrderStatus.Sent\"},{\"key\":\"Purchase\",\"name\":\"App.Prc.OrderStatus.Purchase\"},{\"key\":\"Cancelled\",\"name\":\"App.Prc.OrderStatus.Cancelled\"}]"
|
||||
},
|
||||
"ValidationRuleDto": [],
|
||||
"ColumnStylingDto": [],
|
||||
"PermissionDto": {
|
||||
"Deny": false,
|
||||
"C": "App.Prc.PurchaseOrderAlternative.Create",
|
||||
"R": "App.Prc.PurchaseOrderAlternative",
|
||||
"U": "App.Prc.PurchaseOrderAlternative.Update",
|
||||
"E": true,
|
||||
"I": true
|
||||
},
|
||||
"CanRead": false,
|
||||
"CanCreate": false,
|
||||
"CanUpdate": false,
|
||||
"CanExport": false,
|
||||
"DefaultValue": null,
|
||||
"DefaultValueType": 0,
|
||||
"PivotSettingsDto": {
|
||||
"IsPivot": true,
|
||||
"Expanded": false,
|
||||
"SortOrder": "asc",
|
||||
"Area": "filter",
|
||||
"Format": null,
|
||||
"SummaryType": null,
|
||||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Format": null,
|
||||
"EditOrderNo": null,
|
||||
"EditGroupOrderNo": null,
|
||||
"EditorType2": "dxSelectBox",
|
||||
"ColSpan": 1,
|
||||
"EditorOptions": null,
|
||||
"GridBoxOptions": null,
|
||||
"TagBoxOptions": null,
|
||||
"ImageUploadOptions": null,
|
||||
"EditorScript": null,
|
||||
"LastModificationTime": null,
|
||||
"LastModifierId": null,
|
||||
"CreationTime": "0001-01-01T00:00:00",
|
||||
"CreatorId": null,
|
||||
"Id": "00000000-0000-0000-0000-000000000000"
|
||||
}
|
||||
],
|
||||
"IsDeletedField": false,
|
||||
"IsCreatedField": false,
|
||||
"IsDeletedField": true,
|
||||
"IsCreatedField": true,
|
||||
"InsertedRecords": {
|
||||
"LanguageKeys": [
|
||||
"App.Prc.PurchaseOrderAlternative",
|
||||
"App.Prc.PurchaseOrderAlternative.Title",
|
||||
"App.Prc.PurchaseOrderAlternative.Desc",
|
||||
"App.Prc.OrderStatus.Draft",
|
||||
"App.Prc.OrderStatus.Sent",
|
||||
"App.Prc.OrderStatus.Purchase",
|
||||
"App.Prc.OrderStatus.Cancelled",
|
||||
"App.Listform.ListformField.BaseOrderId",
|
||||
"App.Listform.ListformField.OrderNo",
|
||||
"App.Listform.ListformField.OrderDeadline",
|
||||
"App.Listform.ListformField.ExpectedArrival"
|
||||
"App.Listform.ListformField.BaseId",
|
||||
"App.Listform.ListformField.RfqNo"
|
||||
],
|
||||
"PermissionGroupNames": [],
|
||||
"PermissionNames": [
|
||||
|
|
|
|||
1956
configs/seeds/wizard/Prc_PurchaseOrderImportItem.json
Normal file
1956
configs/seeds/wizard/Prc_PurchaseOrderImportItem.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -3,7 +3,7 @@
|
|||
"ComponentKind": 0,
|
||||
"WizardName": "Prc_PurchaseOrderLine",
|
||||
"WizardCode": "App.Prc.PurchaseOrderLine",
|
||||
"SeededAt": "2026-10-11T00:58:47.5653321+03:00",
|
||||
"SeededAt": "2026-10-11T21:06:00+03:00",
|
||||
"CustomComponentName": null,
|
||||
"PermissionGroupName": "App.Prc",
|
||||
"ModuleId": "Prc",
|
||||
|
|
@ -33,8 +33,8 @@
|
|||
"MenuTr": "Sipariş Kalemleri",
|
||||
"TitleEn": "Order Lines",
|
||||
"TitleTr": "Sipariş Kalemleri",
|
||||
"DescEn": "Order Lines — the products of a request for quotation or purchase order.\nWhere: Purchasing › Orders › Requests for Quotation and Purchase Orders › Products tab (no menu of its own).\nFields: product, description (from the product's purchase description), quantity, unit, unit price, tax rate (from the product's purchase tax rate), amount (quantity × unit price, calculated), material request line (filled by Import from Request, read-only).\nRules: lines cannot be added or deleted on a cancelled document; after every change the document's untaxed amount, tax and total are recalculated.",
|
||||
"DescTr": "Sipariş Kalemleri — teklif talebinin ya da satınalma siparişinin ürünleri.\nNerede: Satınalma › Siparişler › Teklif Talepleri ve Satınalma Siparişleri › Ürünler sekmesi (kendi menüsü yoktur).\nAlanlar: ürün, açıklama (ürünün satınalma açıklamasından), miktar, birim, birim fiyat, vergi oranı (ürünün satınalma vergisinden), tutar (miktar × birim fiyat, hesaplanır), talep kalemi (Talepten Aktar ile dolar, salt okunur).\nKurallar: iptal edilmiş belgeye kalem eklenemez ve silinemez; her değişiklikte belgenin vergi hariç tutarı, KDV'si ve toplamı yeniden hesaplanır."
|
||||
"DescEn": "Order Lines — the products of a purchase order.\nWhere: Purchasing › Orders › Purchase Orders › Products tab (no menu of its own).\nFields: product, description, quantity, unit, unit price, tax rate, amount (quantity × unit price, calculated), delivery date, material request line (read-only).\nRules: lines of a cancelled order cannot be changed; after every change the order totals are recalculated. Lines of an order converted from an RFQ come from the winning RFQ lines.",
|
||||
"DescTr": "Sipariş Kalemleri — satınalma siparişinin ürünleri.\nNerede: Satınalma › Siparişler › Satınalma Siparişleri › Ürünler sekmesi (kendi menüsü yoktur).\nAlanlar: ürün, açıklama, miktar, birim, birim fiyat, vergi oranı, tutar (miktar × birim fiyat, hesaplanır), teslim tarihi, talep kalemi (salt okunur).\nKurallar: iptal edilmiş siparişin kalemi değiştirilemez; her değişiklikte sipariş toplamları yeniden hesaplanır. Teklif talebinden dönüştürülen siparişin kalemleri kazanan teklif kalemlerinden gelir."
|
||||
},
|
||||
"Groups": [
|
||||
{
|
||||
|
|
@ -72,7 +72,7 @@
|
|||
{
|
||||
"FieldName": "UomId",
|
||||
"CaptionName": "App.Listform.ListformField.UomId",
|
||||
"En": "Unit",
|
||||
"En": "Uom",
|
||||
"Tr": "Birim"
|
||||
},
|
||||
{
|
||||
|
|
@ -84,8 +84,8 @@
|
|||
{
|
||||
"FieldName": "TaxRate",
|
||||
"CaptionName": "App.Listform.ListformField.TaxRate",
|
||||
"En": "Taxes (%)",
|
||||
"Tr": "Vergiler (%)"
|
||||
"En": "Tax Rate",
|
||||
"Tr": "Vergi Oran"
|
||||
},
|
||||
{
|
||||
"FieldName": "Amount",
|
||||
|
|
@ -93,6 +93,12 @@
|
|||
"En": "Amount",
|
||||
"Tr": "Tutar"
|
||||
},
|
||||
{
|
||||
"FieldName": "DeliveryDate",
|
||||
"CaptionName": "App.Listform.ListformField.DeliveryDate",
|
||||
"En": "Delivery Date",
|
||||
"Tr": "Teslim Tarihi"
|
||||
},
|
||||
{
|
||||
"FieldName": "MaterialRequestItemId",
|
||||
"CaptionName": "App.Listform.ListformField.MaterialRequestItemId",
|
||||
|
|
@ -117,8 +123,8 @@
|
|||
"SeedSyncUpdate": false,
|
||||
"SeedSyncDelete": false,
|
||||
"DeleteCommand": "UPDATE \"Prc_T_PurchaseOrderLine\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\" IN @Id",
|
||||
"DeleteBeforeCommand": "IF EXISTS (SELECT 1 FROM Prc_T_PurchaseOrderLine l INNER JOIN Prc_T_PurchaseOrder o ON o.Id = l.PurchaseOrderId WHERE l.Id IN @Id AND o.Status = 'Cancelled') THROW 50143, N'İptal edilmiş belgeden kalem silinemez.', 1;",
|
||||
"DeleteAfterCommand": "DECLARE @PoId uniqueidentifier = (SELECT TOP 1 PurchaseOrderId FROM Prc_T_PurchaseOrderLine WHERE Id IN @Id); EXEC Prc_P_PurchaseOrderRecalc @PoId;",
|
||||
"DeleteBeforeCommand": "IF EXISTS (SELECT 1 FROM Prc_T_PurchaseOrderLine l INNER JOIN Prc_T_PurchaseOrder d ON d.Id = l.PurchaseOrderId WHERE l.Id IN @Id AND d.Status IN ('Cancelled')) THROW 50143, N'İptal edilmiş siparişin kalemi silinemez.', 1;",
|
||||
"DeleteAfterCommand": "DECLARE @DocId uniqueidentifier = (SELECT TOP 1 PurchaseOrderId FROM Prc_T_PurchaseOrderLine WHERE Id IN @Id); EXEC Prc_P_PurchaseOrderRecalc @DocId;",
|
||||
"DeleteFieldsDefaultValueDto": [
|
||||
{
|
||||
"FieldName": "DeleterId",
|
||||
|
|
@ -136,7 +142,7 @@
|
|||
}
|
||||
],
|
||||
"InsertCommand": null,
|
||||
"InsertBeforeCommand": "IF EXISTS (SELECT 1 FROM Prc_T_PurchaseOrder WHERE Id = @PurchaseOrderId AND Status = 'Cancelled') THROW 50141, N'İptal edilmiş belgeye kalem eklenemez.', 1;",
|
||||
"InsertBeforeCommand": "IF EXISTS (SELECT 1 FROM Prc_T_PurchaseOrder WHERE Id = @PurchaseOrderId AND Status IN ('Cancelled')) THROW 50141, N'İptal edilmiş siparişe kalem eklenemez.', 1;",
|
||||
"InsertAfterCommand": "EXEC Prc_P_PurchaseOrderRecalc @PurchaseOrderId",
|
||||
"InsertFieldsDefaultValueDto": [
|
||||
{
|
||||
|
|
@ -169,8 +175,8 @@
|
|||
}
|
||||
],
|
||||
"UpdateCommand": null,
|
||||
"UpdateBeforeCommand": "IF EXISTS (SELECT 1 FROM Prc_T_PurchaseOrderLine l INNER JOIN Prc_T_PurchaseOrder o ON o.Id = l.PurchaseOrderId WHERE l.Id = @Id AND o.Status = 'Cancelled') THROW 50142, N'İptal edilmiş belgenin kalemi değiştirilemez.', 1;",
|
||||
"UpdateAfterCommand": "DECLARE @PoId uniqueidentifier = (SELECT TOP 1 PurchaseOrderId FROM Prc_T_PurchaseOrderLine WHERE Id = @Id); EXEC Prc_P_PurchaseOrderRecalc @PoId;",
|
||||
"UpdateBeforeCommand": "IF EXISTS (SELECT 1 FROM Prc_T_PurchaseOrderLine l INNER JOIN Prc_T_PurchaseOrder d ON d.Id = l.PurchaseOrderId WHERE l.Id = @Id AND d.Status IN ('Cancelled')) THROW 50142, N'İptal edilmiş siparişin kalemi değiştirilemez.', 1;",
|
||||
"UpdateAfterCommand": "DECLARE @DocId uniqueidentifier = (SELECT TOP 1 PurchaseOrderId FROM Prc_T_PurchaseOrderLine WHERE Id = @Id); EXEC Prc_P_PurchaseOrderRecalc @DocId;",
|
||||
"UpdateFieldsDefaultValueDto": [
|
||||
{
|
||||
"FieldName": "LastModificationTime",
|
||||
|
|
@ -1909,6 +1915,132 @@
|
|||
"CreatorId": null,
|
||||
"Id": "00000000-0000-0000-0000-000000000000"
|
||||
},
|
||||
{
|
||||
"EditType": null,
|
||||
"ListFormCode": "App.Prc.PurchaseOrderLine",
|
||||
"RoleId": null,
|
||||
"UserId": null,
|
||||
"ColumnJoinTableDto": {
|
||||
"JoinType": null,
|
||||
"TableName": null,
|
||||
"JoinFieldName": null,
|
||||
"BaseTableJoinFieldName": null,
|
||||
"SelectFieldName": null,
|
||||
"FieldNameAlias": null,
|
||||
"JoinCondition2": "AND",
|
||||
"JoinFieldName2": null,
|
||||
"BaseTableJoinFieldName2_OrValue": null
|
||||
},
|
||||
"FieldName": "DeliveryDate",
|
||||
"CaptionName": "App.Listform.ListformField.DeliveryDate",
|
||||
"PlaceHolder": null,
|
||||
"ReadOnly": false,
|
||||
"Visible": true,
|
||||
"IsActive": true,
|
||||
"Width": 0,
|
||||
"ListOrderNo": 10,
|
||||
"SourceDbType": 6,
|
||||
"CultureName": "en",
|
||||
"DataType": "datetime",
|
||||
"SortIndex": 0,
|
||||
"SortDirection": null,
|
||||
"AllowSearch": true,
|
||||
"AllowEditing": true,
|
||||
"AllowAdding": true,
|
||||
"ColumnCssClass": null,
|
||||
"ColumnCssValue": null,
|
||||
"BandName": null,
|
||||
"ColumnFilterDto": {
|
||||
"AllowFiltering": true,
|
||||
"FilterOperations": null,
|
||||
"SelectedFilterOperation": null,
|
||||
"FilterValue": null
|
||||
},
|
||||
"ColumnHeaderDto": {
|
||||
"AllowHeaderFiltering": true,
|
||||
"AllowSearch": false,
|
||||
"DataSource": null,
|
||||
"DataSourceString": ""
|
||||
},
|
||||
"ColumnGroupingDto": {
|
||||
"AllowGrouping": true,
|
||||
"GroupIndex": null,
|
||||
"AutoExpandGroup": false
|
||||
},
|
||||
"ColumnCustomizationDto": {
|
||||
"Fixed": false,
|
||||
"FixedPosition": "left",
|
||||
"AllowReordering": true
|
||||
},
|
||||
"ColumnTotalSummaryDto": {
|
||||
"SummaryType": null,
|
||||
"ValueFormat": null,
|
||||
"ShowInGroupFooter": false,
|
||||
"AlignByColumn": false,
|
||||
"DisplayFormat": null,
|
||||
"ShowInColumn": null
|
||||
},
|
||||
"ColumnGroupSummaryDto": {
|
||||
"SummaryType": null,
|
||||
"ValueFormat": null,
|
||||
"ShowInGroupFooter": false,
|
||||
"AlignByColumn": false,
|
||||
"DisplayFormat": null,
|
||||
"ShowInColumn": null
|
||||
},
|
||||
"LookupDto": {
|
||||
"DataSourceType": 0,
|
||||
"ValueExpr": "Key",
|
||||
"DisplayExpr": "Name",
|
||||
"CascadeRelationField": null,
|
||||
"CascadeFilterOperator": "=",
|
||||
"CascadeParentFields": null,
|
||||
"CascadeEmptyFields": null,
|
||||
"LookupQuery": null
|
||||
},
|
||||
"ValidationRuleDto": [],
|
||||
"ColumnStylingDto": [],
|
||||
"PermissionDto": {
|
||||
"Deny": false,
|
||||
"C": "App.Prc.PurchaseOrderLine.Create",
|
||||
"R": "App.Prc.PurchaseOrderLine",
|
||||
"U": "App.Prc.PurchaseOrderLine.Update",
|
||||
"E": true,
|
||||
"I": true
|
||||
},
|
||||
"CanRead": false,
|
||||
"CanCreate": false,
|
||||
"CanUpdate": false,
|
||||
"CanExport": false,
|
||||
"DefaultValue": null,
|
||||
"DefaultValueType": 0,
|
||||
"PivotSettingsDto": {
|
||||
"IsPivot": true,
|
||||
"Expanded": false,
|
||||
"SortOrder": "asc",
|
||||
"Area": "filter",
|
||||
"Format": null,
|
||||
"SummaryType": null,
|
||||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": 8,
|
||||
"EditGroupOrderNo": 1,
|
||||
"EditorType2": "dxDateBox",
|
||||
"ColSpan": 1,
|
||||
"EditorOptions": "{\"type\":\"date\",\"displayFormat\":\"dd.MM.yyyy\",\"useMaskBehavior\":true,\"showClearButton\":true}",
|
||||
"GridBoxOptions": null,
|
||||
"TagBoxOptions": null,
|
||||
"ImageUploadOptions": null,
|
||||
"EditorScript": null,
|
||||
"LastModificationTime": null,
|
||||
"LastModifierId": null,
|
||||
"CreationTime": "0001-01-01T00:00:00",
|
||||
"CreatorId": null,
|
||||
"Id": "00000000-0000-0000-0000-000000000000"
|
||||
},
|
||||
{
|
||||
"EditType": null,
|
||||
"ListFormCode": "App.Prc.PurchaseOrderLine",
|
||||
|
|
@ -1932,7 +2064,7 @@
|
|||
"Visible": true,
|
||||
"IsActive": true,
|
||||
"Width": 0,
|
||||
"ListOrderNo": 10,
|
||||
"ListOrderNo": 11,
|
||||
"SourceDbType": 9,
|
||||
"CultureName": "en",
|
||||
"DataType": "string",
|
||||
|
|
@ -2020,7 +2152,7 @@
|
|||
},
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": 8,
|
||||
"EditOrderNo": 9,
|
||||
"EditGroupOrderNo": 1,
|
||||
"EditorType2": "dxSelectBox",
|
||||
"ColSpan": 1,
|
||||
|
|
@ -2042,8 +2174,7 @@
|
|||
"LanguageKeys": [
|
||||
"App.Prc.PurchaseOrderLine",
|
||||
"App.Prc.PurchaseOrderLine.Title",
|
||||
"App.Prc.PurchaseOrderLine.Desc",
|
||||
"App.Listform.ListformField.MaterialRequestItemId"
|
||||
"App.Prc.PurchaseOrderLine.Desc"
|
||||
],
|
||||
"PermissionGroupNames": [],
|
||||
"PermissionNames": [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"ComponentKind": 0,
|
||||
"WizardName": "Prc_PurchaseOrderOther",
|
||||
"WizardCode": "App.Prc.PurchaseOrderOther",
|
||||
"SeededAt": "2026-10-11T00:59:35.4134542+03:00",
|
||||
"SeededAt": "2026-10-11T21:08:00+03:00",
|
||||
"CustomComponentName": null,
|
||||
"PermissionGroupName": "App.Prc",
|
||||
"ModuleId": "Prc",
|
||||
|
|
@ -33,8 +33,8 @@
|
|||
"MenuTr": "Diğer Bilgiler",
|
||||
"TitleEn": "Other Information",
|
||||
"TitleTr": "Diğer Bilgiler",
|
||||
"DescEn": "Other Information — buyer, source, project and commercial terms of an RFQ or purchase order.\nWhere: Purchasing › Orders › Requests for Quotation and Purchase Orders › Other Information tab (no menu of its own; edits the document record itself).\nFields: buyer, source (material request numbers of the lines, written automatically, read-only), project, delivery term (Incoterm) and Incoterm location, payment term.\nDefaults: buyer, delivery term and payment term come from the supplier's Purchasing tab on the contact card.",
|
||||
"DescTr": "Diğer Bilgiler — teklif talebinin ya da satınalma siparişinin alıcı, kaynak, proje ve ticari koşulları.\nNerede: Satınalma › Siparişler › Teklif Talepleri ve Satınalma Siparişleri › Diğer Bilgiler sekmesi (kendi menüsü yoktur; belge kaydının kendisini düzenler).\nAlanlar: alıcı, kaynak (kalemlerin malzeme talebi numaraları, otomatik yazılır, salt okunur), proje, teslimat koşulu (Incoterm) ve Incoterm konumu, ödeme koşulu.\nVarsayılanlar: alıcı, teslimat ve ödeme koşulu tedarikçinin kontak kartındaki Satınalma sekmesinden gelir."
|
||||
"DescEn": "Other Information — buyer, project and commercial terms of a purchase order.\nWhere: Purchasing › Orders › Purchase Orders › Other Information tab (no menu of its own; edits the order record itself).\nFields: buyer, payment term, project, delivery term (Incoterm) and its location.\nDefaults: buyer, payment and delivery terms come from the supplier's Purchasing tab on the contact card, or from the RFQ the order was converted from.",
|
||||
"DescTr": "Diğer Bilgiler — satınalma siparişinin alıcı, proje ve ticari koşulları.\nNerede: Satınalma › Siparişler › Satınalma Siparişleri › Diğer Bilgiler sekmesi (kendi menüsü yoktur; sipariş kaydının kendisini düzenler).\nAlanlar: alıcı, ödeme koşulu, proje, teslimat koşulu (Incoterm) ve konumu.\nVarsayılanlar: alıcı, ödeme ve teslimat koşulu tedarikçinin kontak kartındaki Satınalma sekmesinden ya da siparişin dönüştürüldüğü teklif talebinden gelir."
|
||||
},
|
||||
"Groups": [
|
||||
{
|
||||
|
|
@ -54,14 +54,8 @@
|
|||
{
|
||||
"FieldName": "PaymentTermId",
|
||||
"CaptionName": "App.Listform.ListformField.PaymentTermId",
|
||||
"En": "Payment Terms",
|
||||
"Tr": "Ödeme Koşulları"
|
||||
},
|
||||
{
|
||||
"FieldName": "SourceDocument",
|
||||
"CaptionName": "App.Listform.ListformField.SourceDocument",
|
||||
"En": "Source",
|
||||
"Tr": "Kaynak"
|
||||
"En": "Payment Term",
|
||||
"Tr": "Ödeme Süresi"
|
||||
},
|
||||
{
|
||||
"FieldName": "ProjectId",
|
||||
|
|
@ -151,7 +145,7 @@
|
|||
}
|
||||
],
|
||||
"UpdateCommand": null,
|
||||
"UpdateBeforeCommand": null,
|
||||
"UpdateBeforeCommand": "IF EXISTS (SELECT 1 FROM Prc_T_PurchaseOrder WHERE Id = @Id AND Status = 'Cancelled') THROW 50154, N'İptal edilmiş sipariş değiştirilemez.', 1;",
|
||||
"UpdateAfterCommand": null,
|
||||
"UpdateFieldsDefaultValueDto": [
|
||||
{
|
||||
|
|
@ -798,7 +792,7 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": null,
|
||||
"EditGroupOrderNo": null,
|
||||
|
|
@ -936,7 +930,7 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": 1,
|
||||
"EditGroupOrderNo": 1,
|
||||
|
|
@ -1062,7 +1056,7 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": 2,
|
||||
"EditGroupOrderNo": 1,
|
||||
|
|
@ -1079,132 +1073,6 @@
|
|||
"CreatorId": null,
|
||||
"Id": "00000000-0000-0000-0000-000000000000"
|
||||
},
|
||||
{
|
||||
"EditType": null,
|
||||
"ListFormCode": "App.Prc.PurchaseOrderOther",
|
||||
"RoleId": null,
|
||||
"UserId": null,
|
||||
"ColumnJoinTableDto": {
|
||||
"JoinType": null,
|
||||
"TableName": null,
|
||||
"JoinFieldName": null,
|
||||
"BaseTableJoinFieldName": null,
|
||||
"SelectFieldName": null,
|
||||
"FieldNameAlias": null,
|
||||
"JoinCondition2": "AND",
|
||||
"JoinFieldName2": null,
|
||||
"BaseTableJoinFieldName2_OrValue": null
|
||||
},
|
||||
"FieldName": "SourceDocument",
|
||||
"CaptionName": "App.Listform.ListformField.SourceDocument",
|
||||
"PlaceHolder": null,
|
||||
"ReadOnly": false,
|
||||
"Visible": true,
|
||||
"IsActive": true,
|
||||
"Width": 0,
|
||||
"ListOrderNo": 4,
|
||||
"SourceDbType": 16,
|
||||
"CultureName": "en",
|
||||
"DataType": "string",
|
||||
"SortIndex": 0,
|
||||
"SortDirection": null,
|
||||
"AllowSearch": true,
|
||||
"AllowEditing": true,
|
||||
"AllowAdding": true,
|
||||
"ColumnCssClass": null,
|
||||
"ColumnCssValue": null,
|
||||
"BandName": null,
|
||||
"ColumnFilterDto": {
|
||||
"AllowFiltering": true,
|
||||
"FilterOperations": null,
|
||||
"SelectedFilterOperation": null,
|
||||
"FilterValue": null
|
||||
},
|
||||
"ColumnHeaderDto": {
|
||||
"AllowHeaderFiltering": true,
|
||||
"AllowSearch": false,
|
||||
"DataSource": null,
|
||||
"DataSourceString": ""
|
||||
},
|
||||
"ColumnGroupingDto": {
|
||||
"AllowGrouping": true,
|
||||
"GroupIndex": null,
|
||||
"AutoExpandGroup": false
|
||||
},
|
||||
"ColumnCustomizationDto": {
|
||||
"Fixed": false,
|
||||
"FixedPosition": "left",
|
||||
"AllowReordering": true
|
||||
},
|
||||
"ColumnTotalSummaryDto": {
|
||||
"SummaryType": null,
|
||||
"ValueFormat": null,
|
||||
"ShowInGroupFooter": false,
|
||||
"AlignByColumn": false,
|
||||
"DisplayFormat": null,
|
||||
"ShowInColumn": null
|
||||
},
|
||||
"ColumnGroupSummaryDto": {
|
||||
"SummaryType": null,
|
||||
"ValueFormat": null,
|
||||
"ShowInGroupFooter": false,
|
||||
"AlignByColumn": false,
|
||||
"DisplayFormat": null,
|
||||
"ShowInColumn": null
|
||||
},
|
||||
"LookupDto": {
|
||||
"DataSourceType": 0,
|
||||
"ValueExpr": "Key",
|
||||
"DisplayExpr": "Name",
|
||||
"CascadeRelationField": null,
|
||||
"CascadeFilterOperator": "=",
|
||||
"CascadeParentFields": null,
|
||||
"CascadeEmptyFields": null,
|
||||
"LookupQuery": null
|
||||
},
|
||||
"ValidationRuleDto": [],
|
||||
"ColumnStylingDto": [],
|
||||
"PermissionDto": {
|
||||
"Deny": false,
|
||||
"C": "App.Prc.PurchaseOrderOther.Create",
|
||||
"R": "App.Prc.PurchaseOrderOther",
|
||||
"U": "App.Prc.PurchaseOrderOther.Update",
|
||||
"E": true,
|
||||
"I": true
|
||||
},
|
||||
"CanRead": false,
|
||||
"CanCreate": false,
|
||||
"CanUpdate": false,
|
||||
"CanExport": false,
|
||||
"DefaultValue": null,
|
||||
"DefaultValueType": 0,
|
||||
"PivotSettingsDto": {
|
||||
"IsPivot": true,
|
||||
"Expanded": false,
|
||||
"SortOrder": "asc",
|
||||
"Area": "filter",
|
||||
"Format": null,
|
||||
"SummaryType": null,
|
||||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Format": null,
|
||||
"EditOrderNo": 3,
|
||||
"EditGroupOrderNo": 1,
|
||||
"EditorType2": "dxTextBox",
|
||||
"ColSpan": 1,
|
||||
"EditorOptions": "{\"readOnly\":true}",
|
||||
"GridBoxOptions": null,
|
||||
"TagBoxOptions": null,
|
||||
"ImageUploadOptions": null,
|
||||
"EditorScript": null,
|
||||
"LastModificationTime": null,
|
||||
"LastModifierId": null,
|
||||
"CreationTime": "0001-01-01T00:00:00",
|
||||
"CreatorId": null,
|
||||
"Id": "00000000-0000-0000-0000-000000000000"
|
||||
},
|
||||
{
|
||||
"EditType": null,
|
||||
"ListFormCode": "App.Prc.PurchaseOrderOther",
|
||||
|
|
@ -1228,7 +1096,7 @@
|
|||
"Visible": true,
|
||||
"IsActive": true,
|
||||
"Width": 0,
|
||||
"ListOrderNo": 5,
|
||||
"ListOrderNo": 4,
|
||||
"SourceDbType": 9,
|
||||
"CultureName": "en",
|
||||
"DataType": "string",
|
||||
|
|
@ -1314,9 +1182,9 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": 4,
|
||||
"EditOrderNo": 3,
|
||||
"EditGroupOrderNo": 1,
|
||||
"EditorType2": "dxSelectBox",
|
||||
"ColSpan": 1,
|
||||
|
|
@ -1354,7 +1222,7 @@
|
|||
"Visible": true,
|
||||
"IsActive": true,
|
||||
"Width": 0,
|
||||
"ListOrderNo": 6,
|
||||
"ListOrderNo": 5,
|
||||
"SourceDbType": 9,
|
||||
"CultureName": "en",
|
||||
"DataType": "string",
|
||||
|
|
@ -1440,9 +1308,9 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": 5,
|
||||
"EditOrderNo": 4,
|
||||
"EditGroupOrderNo": 1,
|
||||
"EditorType2": "dxSelectBox",
|
||||
"ColSpan": 1,
|
||||
|
|
@ -1480,7 +1348,7 @@
|
|||
"Visible": true,
|
||||
"IsActive": true,
|
||||
"Width": 0,
|
||||
"ListOrderNo": 7,
|
||||
"ListOrderNo": 6,
|
||||
"SourceDbType": 16,
|
||||
"CultureName": "en",
|
||||
"DataType": "string",
|
||||
|
|
@ -1566,9 +1434,9 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": 6,
|
||||
"EditOrderNo": 5,
|
||||
"EditGroupOrderNo": 1,
|
||||
"EditorType2": "dxTextBox",
|
||||
"ColSpan": 1,
|
||||
|
|
@ -1590,10 +1458,7 @@
|
|||
"LanguageKeys": [
|
||||
"App.Prc.PurchaseOrderOther",
|
||||
"App.Prc.PurchaseOrderOther.Title",
|
||||
"App.Prc.PurchaseOrderOther.Desc",
|
||||
"App.Listform.ListformField.SourceDocument",
|
||||
"App.Listform.ListformField.IncotermId",
|
||||
"App.Listform.ListformField.IncotermLocation"
|
||||
"App.Prc.PurchaseOrderOther.Desc"
|
||||
],
|
||||
"PermissionGroupNames": [],
|
||||
"PermissionNames": [
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
2107
configs/seeds/wizard/Prc_PurchaseRfqAlternative.json
Normal file
2107
configs/seeds/wizard/Prc_PurchaseRfqAlternative.json
Normal file
File diff suppressed because it is too large
Load diff
2778
configs/seeds/wizard/Prc_PurchaseRfqComparison.json
Normal file
2778
configs/seeds/wizard/Prc_PurchaseRfqComparison.json
Normal file
File diff suppressed because it is too large
Load diff
1956
configs/seeds/wizard/Prc_PurchaseRfqImportItem.json
Normal file
1956
configs/seeds/wizard/Prc_PurchaseRfqImportItem.json
Normal file
File diff suppressed because it is too large
Load diff
2198
configs/seeds/wizard/Prc_PurchaseRfqLine.json
Normal file
2198
configs/seeds/wizard/Prc_PurchaseRfqLine.json
Normal file
File diff suppressed because it is too large
Load diff
1771
configs/seeds/wizard/Prc_PurchaseRfqOther.json
Normal file
1771
configs/seeds/wizard/Prc_PurchaseRfqOther.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"Wizard": {
|
||||
"ComponentKind": 0,
|
||||
"WizardName": "Prc_PurchaseOrderQuote",
|
||||
"WizardCode": "App.Prc.PurchaseOrderQuote",
|
||||
"SeededAt": "2026-10-11T00:59:10.1491792+03:00",
|
||||
"WizardName": "Prc_PurchaseRfqQuote",
|
||||
"WizardCode": "App.Prc.PurchaseRfqQuote",
|
||||
"SeededAt": "2026-10-11T21:02:00+03:00",
|
||||
"CustomComponentName": null,
|
||||
"PermissionGroupName": "App.Prc",
|
||||
"ModuleId": "Prc",
|
||||
|
|
@ -19,9 +19,9 @@
|
|||
"MenuParentCode": "App.Prc.Orders",
|
||||
"MenuParentIcon": "FcShop",
|
||||
"CreateMenu": false,
|
||||
"MenuCode": "App.Prc.PurchaseOrderQuote",
|
||||
"MenuCode": "App.Prc.PurchaseRfqQuote",
|
||||
"MenuOrder": 0,
|
||||
"MenuUrl": "/admin/list/App.Prc.PurchaseOrderQuote",
|
||||
"MenuUrl": "/admin/list/App.Prc.PurchaseRfqQuote",
|
||||
"MenuIcon": "FcCollaboration"
|
||||
},
|
||||
"Language": {
|
||||
|
|
@ -33,25 +33,8 @@
|
|||
"MenuTr": "Tedarikçi Teklifi",
|
||||
"TitleEn": "Supplier Quote",
|
||||
"TitleTr": "Tedarikçi Teklifi",
|
||||
"DescEn": "Supplier Quote — the supplier's answer to a request for quotation.\nWhere: Purchasing › Orders › Requests for Quotation › Supplier Quote tab (no menu of its own; edits the RFQ record itself).\nFields: supplier response (Waiting / Quoted / Not Quoted), quote date, quoted by (the user who entered the quote), quote validity date.\nUsage: when the response leaves Waiting, an empty quote date and quoted-by are filled automatically; quoted prices are entered on the Products tab.",
|
||||
"DescTr": "Tedarikçi Teklifi — tedarikçinin teklif talebine verdiği yanıt.\nNerede: Satınalma › Siparişler › Teklif Talepleri › Tedarikçi Teklifi sekmesi (kendi menüsü yoktur; teklif kaydının kendisini düzenler).\nAlanlar: tedarikçi yanıtı (Bekleniyor / Teklif Verildi / Teklif Verilmedi), teklif tarihi, teklifi veren (teklifi sisteme işleyen kullanıcı), teklif geçerlilik tarihi.\nKullanım: yanıt Bekleniyor dışına alınınca boş teklif tarihi ve teklifi veren otomatik dolar; teklif edilen fiyatlar Ürünler sekmesine girilir.",
|
||||
"Texts": [
|
||||
{
|
||||
"Key": "App.Prc.SupplierResponse.Waiting",
|
||||
"En": "Waiting",
|
||||
"Tr": "Bekleniyor"
|
||||
},
|
||||
{
|
||||
"Key": "App.Prc.SupplierResponse.Quoted",
|
||||
"En": "Quoted",
|
||||
"Tr": "Teklif Verildi"
|
||||
},
|
||||
{
|
||||
"Key": "App.Prc.SupplierResponse.NotQuoted",
|
||||
"En": "Not Quoted",
|
||||
"Tr": "Teklif Verilmedi"
|
||||
}
|
||||
]
|
||||
"DescEn": "Supplier Quote — the supplier's answer to a request for quotation.\nWhere: Purchasing › Orders › Requests for Quotation › Supplier Quote tab (no menu of its own; edits the RFQ record itself).\nFields: supplier response (Waiting / Quoted / Not Quoted), quote date, quote validity date.\nUsage: when the response leaves Waiting an empty quote date is filled; quoted prices and delivery dates are entered on the Products tab or in the Price Comparison tab. An RFQ answered Not Quoted is left out of the comparison.",
|
||||
"DescTr": "Tedarikçi Teklifi — tedarikçinin teklif talebine verdiği yanıt.\nNerede: Satınalma › Siparişler › Teklif Talepleri › Tedarikçi Teklifi sekmesi (kendi menüsü yoktur; teklif kaydının kendisini düzenler).\nAlanlar: tedarikçi yanıtı (Bekleniyor / Teklif Verildi / Teklif Verilmedi), teklif tarihi, teklif geçerlilik tarihi.\nKullanım: yanıt Bekleniyor dışına alınınca boş teklif tarihi dolar; teklif edilen fiyat ve terminler Ürünler ya da Fiyat Karşılaştırması sekmesine girilir. Teklif Verilmedi yanıtlı belge kıyasa girmez."
|
||||
},
|
||||
"Groups": [
|
||||
{
|
||||
|
|
@ -68,12 +51,6 @@
|
|||
"En": "Supplier Response",
|
||||
"Tr": "Tedarikçi Yanıtı"
|
||||
},
|
||||
{
|
||||
"FieldName": "QuoteValidUntil",
|
||||
"CaptionName": "App.Listform.ListformField.QuoteValidUntil",
|
||||
"En": "Quote Validity",
|
||||
"Tr": "Teklif Geçerliliği"
|
||||
},
|
||||
{
|
||||
"FieldName": "QuoteDate",
|
||||
"CaptionName": "App.Listform.ListformField.QuoteDate",
|
||||
|
|
@ -81,10 +58,10 @@
|
|||
"Tr": "Teklif Tarihi"
|
||||
},
|
||||
{
|
||||
"FieldName": "QuotedByUserId",
|
||||
"CaptionName": "App.Listform.ListformField.QuotedByUserId",
|
||||
"En": "Quoted By",
|
||||
"Tr": "Teklifi Veren"
|
||||
"FieldName": "QuoteValidUntil",
|
||||
"CaptionName": "App.Listform.ListformField.QuoteValidUntil",
|
||||
"En": "Quote Validity",
|
||||
"Tr": "Teklif Geçerliliği"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -96,14 +73,14 @@
|
|||
"KeyFieldDbSourceType": 9,
|
||||
"TableName": null,
|
||||
"DefaultFilter": "\"IsDeleted\" = 'false'",
|
||||
"SelectCommand": "Prc_T_PurchaseOrder",
|
||||
"SelectCommand": "Prc_T_PurchaseRfq",
|
||||
"SelectCommandType": 1,
|
||||
"SelectFieldsDefaultValueDto": [],
|
||||
"SeedFilePath": null,
|
||||
"SeedSyncInsert": false,
|
||||
"SeedSyncUpdate": false,
|
||||
"SeedSyncDelete": false,
|
||||
"DeleteCommand": "UPDATE \"Prc_T_PurchaseOrder\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\" IN @Id",
|
||||
"DeleteCommand": "UPDATE \"Prc_T_PurchaseRfq\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\" IN @Id",
|
||||
"DeleteBeforeCommand": null,
|
||||
"DeleteAfterCommand": null,
|
||||
"DeleteFieldsDefaultValueDto": [
|
||||
|
|
@ -156,8 +133,8 @@
|
|||
}
|
||||
],
|
||||
"UpdateCommand": null,
|
||||
"UpdateBeforeCommand": null,
|
||||
"UpdateAfterCommand": "UPDATE Prc_T_PurchaseOrder SET QuoteDate = ISNULL(QuoteDate, GETUTCDATE()), QuotedByUserId = ISNULL(QuotedByUserId, LastModifierId) WHERE Id = @Id AND SupplierResponse <> 'Waiting';",
|
||||
"UpdateBeforeCommand": "IF EXISTS (SELECT 1 FROM Prc_T_PurchaseRfq WHERE Id = @Id AND Status IN ('Purchase', 'Cancelled')) THROW 50151, N'Siparişe dönüştürülmüş ya da iptal edilmiş teklif değiştirilemez.', 1;",
|
||||
"UpdateAfterCommand": "EXEC Prc_P_PurchaseRfqAfterSave @Id, @LastModifierId",
|
||||
"UpdateFieldsDefaultValueDto": [
|
||||
{
|
||||
"FieldName": "LastModificationTime",
|
||||
|
|
@ -180,22 +157,22 @@
|
|||
"FieldDbType": 16,
|
||||
"Value": "Waiting",
|
||||
"CustomValueType": 1,
|
||||
"SqlQuery": null
|
||||
"SqlQuery": ""
|
||||
}
|
||||
],
|
||||
"WidgetsDto": [],
|
||||
"ExtraFilterEditDto": [],
|
||||
"ListFormCode": "App.Prc.PurchaseOrderQuote",
|
||||
"ListFormCode": "App.Prc.PurchaseRfqQuote",
|
||||
"CultureName": "en",
|
||||
"Name": "App.Prc.PurchaseOrderQuote",
|
||||
"Name": "App.Prc.PurchaseRfqQuote",
|
||||
"KeyFieldName": "Id",
|
||||
"Title": "App.Prc.PurchaseOrderQuote.Title",
|
||||
"Title": "App.Prc.PurchaseRfqQuote.Title",
|
||||
"SortMode": "single",
|
||||
"PageSize": 10,
|
||||
"Width": 0,
|
||||
"Height": 0,
|
||||
"FullHeight": false,
|
||||
"Description": "App.Prc.PurchaseOrderQuote.Desc",
|
||||
"Description": "App.Prc.PurchaseRfqQuote.Desc",
|
||||
"FilterRowDto": {
|
||||
"Visible": true,
|
||||
"ApplyFilter": "auto",
|
||||
|
|
@ -367,7 +344,7 @@
|
|||
"StartEditAction": "click",
|
||||
"EditColumnName": null,
|
||||
"Popup": {
|
||||
"Title": "App.Prc.PurchaseOrderQuote.Title",
|
||||
"Title": "App.Prc.PurchaseRfqQuote.Title",
|
||||
"ShowTitle": true,
|
||||
"Width": 800,
|
||||
"Height": 275,
|
||||
|
|
@ -393,19 +370,19 @@
|
|||
}
|
||||
],
|
||||
"PermissionDto": {
|
||||
"C": "App.Prc.PurchaseOrderQuote.Create",
|
||||
"R": "App.Prc.PurchaseOrderQuote",
|
||||
"U": "App.Prc.PurchaseOrderQuote.Update",
|
||||
"D": "App.Prc.PurchaseOrderQuote.Delete",
|
||||
"E": "App.Prc.PurchaseOrderQuote.Export",
|
||||
"I": "App.Prc.PurchaseOrderQuote.Import",
|
||||
"N": "App.Prc.PurchaseOrderQuote.Note"
|
||||
"C": "App.Prc.PurchaseRfqQuote.Create",
|
||||
"R": "App.Prc.PurchaseRfqQuote",
|
||||
"U": "App.Prc.PurchaseRfqQuote.Update",
|
||||
"D": "App.Prc.PurchaseRfqQuote.Delete",
|
||||
"E": "App.Prc.PurchaseRfqQuote.Export",
|
||||
"I": "App.Prc.PurchaseRfqQuote.Import",
|
||||
"N": "App.Prc.PurchaseRfqQuote.Note"
|
||||
},
|
||||
"CommandColumnDto": [],
|
||||
"StateStoringDto": {
|
||||
"Enabled": true,
|
||||
"Type": "custom",
|
||||
"StorageKey": "listFormGridStorage-App.Prc.PurchaseOrderQuote",
|
||||
"StorageKey": "listFormGridStorage-App.Prc.PurchaseRfqQuote",
|
||||
"SavingTimeout": 5000
|
||||
},
|
||||
"CustomJsSources": [],
|
||||
|
|
@ -704,7 +681,7 @@
|
|||
"Fields": [
|
||||
{
|
||||
"EditType": null,
|
||||
"ListFormCode": "App.Prc.PurchaseOrderQuote",
|
||||
"ListFormCode": "App.Prc.PurchaseRfqQuote",
|
||||
"RoleId": null,
|
||||
"UserId": null,
|
||||
"ColumnJoinTableDto": {
|
||||
|
|
@ -789,9 +766,9 @@
|
|||
"ColumnStylingDto": [],
|
||||
"PermissionDto": {
|
||||
"Deny": false,
|
||||
"C": "App.Prc.PurchaseOrderQuote.Create",
|
||||
"R": "App.Prc.PurchaseOrderQuote",
|
||||
"U": "App.Prc.PurchaseOrderQuote.Update",
|
||||
"C": "App.Prc.PurchaseRfqQuote.Create",
|
||||
"R": "App.Prc.PurchaseRfqQuote",
|
||||
"U": "App.Prc.PurchaseRfqQuote.Update",
|
||||
"E": true,
|
||||
"I": true
|
||||
},
|
||||
|
|
@ -811,7 +788,7 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": null,
|
||||
"EditGroupOrderNo": null,
|
||||
|
|
@ -830,7 +807,7 @@
|
|||
},
|
||||
{
|
||||
"EditType": null,
|
||||
"ListFormCode": "App.Prc.PurchaseOrderQuote",
|
||||
"ListFormCode": "App.Prc.PurchaseRfqQuote",
|
||||
"RoleId": null,
|
||||
"UserId": null,
|
||||
"ColumnJoinTableDto": {
|
||||
|
|
@ -927,9 +904,9 @@
|
|||
"ColumnStylingDto": [],
|
||||
"PermissionDto": {
|
||||
"Deny": false,
|
||||
"C": "App.Prc.PurchaseOrderQuote.Create",
|
||||
"R": "App.Prc.PurchaseOrderQuote",
|
||||
"U": "App.Prc.PurchaseOrderQuote.Update",
|
||||
"C": "App.Prc.PurchaseRfqQuote.Create",
|
||||
"R": "App.Prc.PurchaseRfqQuote",
|
||||
"U": "App.Prc.PurchaseRfqQuote.Update",
|
||||
"E": true,
|
||||
"I": true
|
||||
},
|
||||
|
|
@ -949,7 +926,7 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": 1,
|
||||
"EditGroupOrderNo": 1,
|
||||
|
|
@ -968,7 +945,7 @@
|
|||
},
|
||||
{
|
||||
"EditType": null,
|
||||
"ListFormCode": "App.Prc.PurchaseOrderQuote",
|
||||
"ListFormCode": "App.Prc.PurchaseRfqQuote",
|
||||
"RoleId": null,
|
||||
"UserId": null,
|
||||
"ColumnJoinTableDto": {
|
||||
|
|
@ -982,8 +959,8 @@
|
|||
"JoinFieldName2": null,
|
||||
"BaseTableJoinFieldName2_OrValue": null
|
||||
},
|
||||
"FieldName": "QuoteValidUntil",
|
||||
"CaptionName": "App.Listform.ListformField.QuoteValidUntil",
|
||||
"FieldName": "QuoteDate",
|
||||
"CaptionName": "App.Listform.ListformField.QuoteDate",
|
||||
"PlaceHolder": null,
|
||||
"ReadOnly": false,
|
||||
"Visible": true,
|
||||
|
|
@ -1053,9 +1030,9 @@
|
|||
"ColumnStylingDto": [],
|
||||
"PermissionDto": {
|
||||
"Deny": false,
|
||||
"C": "App.Prc.PurchaseOrderQuote.Create",
|
||||
"R": "App.Prc.PurchaseOrderQuote",
|
||||
"U": "App.Prc.PurchaseOrderQuote.Update",
|
||||
"C": "App.Prc.PurchaseRfqQuote.Create",
|
||||
"R": "App.Prc.PurchaseRfqQuote",
|
||||
"U": "App.Prc.PurchaseRfqQuote.Update",
|
||||
"E": true,
|
||||
"I": true
|
||||
},
|
||||
|
|
@ -1075,13 +1052,13 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": 2,
|
||||
"EditGroupOrderNo": 1,
|
||||
"EditorType2": "dxDateBox",
|
||||
"ColSpan": 1,
|
||||
"EditorOptions": "{\"type\":\"date\",\"displayFormat\":\"dd.MM.yyyy\",\"useMaskBehavior\":true,\"showClearButton\":true}",
|
||||
"EditorOptions": "{\"type\":\"datetime\",\"displayFormat\":\"dd.MM.yyyy HH:mm\",\"useMaskBehavior\":true,\"showClearButton\":true}",
|
||||
"GridBoxOptions": null,
|
||||
"TagBoxOptions": null,
|
||||
"ImageUploadOptions": null,
|
||||
|
|
@ -1094,7 +1071,7 @@
|
|||
},
|
||||
{
|
||||
"EditType": null,
|
||||
"ListFormCode": "App.Prc.PurchaseOrderQuote",
|
||||
"ListFormCode": "App.Prc.PurchaseRfqQuote",
|
||||
"RoleId": null,
|
||||
"UserId": null,
|
||||
"ColumnJoinTableDto": {
|
||||
|
|
@ -1108,8 +1085,8 @@
|
|||
"JoinFieldName2": null,
|
||||
"BaseTableJoinFieldName2_OrValue": null
|
||||
},
|
||||
"FieldName": "QuoteDate",
|
||||
"CaptionName": "App.Listform.ListformField.QuoteDate",
|
||||
"FieldName": "QuoteValidUntil",
|
||||
"CaptionName": "App.Listform.ListformField.QuoteValidUntil",
|
||||
"PlaceHolder": null,
|
||||
"ReadOnly": false,
|
||||
"Visible": true,
|
||||
|
|
@ -1179,9 +1156,9 @@
|
|||
"ColumnStylingDto": [],
|
||||
"PermissionDto": {
|
||||
"Deny": false,
|
||||
"C": "App.Prc.PurchaseOrderQuote.Create",
|
||||
"R": "App.Prc.PurchaseOrderQuote",
|
||||
"U": "App.Prc.PurchaseOrderQuote.Update",
|
||||
"C": "App.Prc.PurchaseRfqQuote.Create",
|
||||
"R": "App.Prc.PurchaseRfqQuote",
|
||||
"U": "App.Prc.PurchaseRfqQuote.Update",
|
||||
"E": true,
|
||||
"I": true
|
||||
},
|
||||
|
|
@ -1201,139 +1178,13 @@
|
|||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Alignment": "left",
|
||||
"Format": null,
|
||||
"EditOrderNo": 3,
|
||||
"EditGroupOrderNo": 1,
|
||||
"EditorType2": "dxDateBox",
|
||||
"ColSpan": 1,
|
||||
"EditorOptions": "{\"type\":\"datetime\",\"displayFormat\":\"dd.MM.yyyy HH:mm\",\"useMaskBehavior\":true,\"showClearButton\":true}",
|
||||
"GridBoxOptions": null,
|
||||
"TagBoxOptions": null,
|
||||
"ImageUploadOptions": null,
|
||||
"EditorScript": null,
|
||||
"LastModificationTime": null,
|
||||
"LastModifierId": null,
|
||||
"CreationTime": "0001-01-01T00:00:00",
|
||||
"CreatorId": null,
|
||||
"Id": "00000000-0000-0000-0000-000000000000"
|
||||
},
|
||||
{
|
||||
"EditType": null,
|
||||
"ListFormCode": "App.Prc.PurchaseOrderQuote",
|
||||
"RoleId": null,
|
||||
"UserId": null,
|
||||
"ColumnJoinTableDto": {
|
||||
"JoinType": null,
|
||||
"TableName": null,
|
||||
"JoinFieldName": null,
|
||||
"BaseTableJoinFieldName": null,
|
||||
"SelectFieldName": null,
|
||||
"FieldNameAlias": null,
|
||||
"JoinCondition2": "AND",
|
||||
"JoinFieldName2": null,
|
||||
"BaseTableJoinFieldName2_OrValue": null
|
||||
},
|
||||
"FieldName": "QuotedByUserId",
|
||||
"CaptionName": "App.Listform.ListformField.QuotedByUserId",
|
||||
"PlaceHolder": null,
|
||||
"ReadOnly": false,
|
||||
"Visible": true,
|
||||
"IsActive": true,
|
||||
"Width": 0,
|
||||
"ListOrderNo": 5,
|
||||
"SourceDbType": 9,
|
||||
"CultureName": "en",
|
||||
"DataType": "string",
|
||||
"SortIndex": 0,
|
||||
"SortDirection": null,
|
||||
"AllowSearch": true,
|
||||
"AllowEditing": true,
|
||||
"AllowAdding": true,
|
||||
"ColumnCssClass": null,
|
||||
"ColumnCssValue": null,
|
||||
"BandName": null,
|
||||
"ColumnFilterDto": {
|
||||
"AllowFiltering": true,
|
||||
"FilterOperations": null,
|
||||
"SelectedFilterOperation": null,
|
||||
"FilterValue": null
|
||||
},
|
||||
"ColumnHeaderDto": {
|
||||
"AllowHeaderFiltering": true,
|
||||
"AllowSearch": false,
|
||||
"DataSource": null,
|
||||
"DataSourceString": ""
|
||||
},
|
||||
"ColumnGroupingDto": {
|
||||
"AllowGrouping": true,
|
||||
"GroupIndex": null,
|
||||
"AutoExpandGroup": false
|
||||
},
|
||||
"ColumnCustomizationDto": {
|
||||
"Fixed": false,
|
||||
"FixedPosition": "left",
|
||||
"AllowReordering": true
|
||||
},
|
||||
"ColumnTotalSummaryDto": {
|
||||
"SummaryType": null,
|
||||
"ValueFormat": null,
|
||||
"ShowInGroupFooter": false,
|
||||
"AlignByColumn": false,
|
||||
"DisplayFormat": null,
|
||||
"ShowInColumn": null
|
||||
},
|
||||
"ColumnGroupSummaryDto": {
|
||||
"SummaryType": null,
|
||||
"ValueFormat": null,
|
||||
"ShowInGroupFooter": false,
|
||||
"AlignByColumn": false,
|
||||
"DisplayFormat": null,
|
||||
"ShowInColumn": null
|
||||
},
|
||||
"LookupDto": {
|
||||
"DataSourceType": 2,
|
||||
"ValueExpr": "Key",
|
||||
"DisplayExpr": "Name",
|
||||
"CascadeRelationField": null,
|
||||
"CascadeFilterOperator": "=",
|
||||
"CascadeParentFields": null,
|
||||
"CascadeEmptyFields": null,
|
||||
"LookupQuery": "SELECT Id AS [Key], CONCAT(Name, ' ', Surname) AS [Name] FROM AbpUsers WHERE IsDeleted = 'false' AND IsActive = 1 AND TenantId = '@TENANTID' ORDER BY Name, Surname"
|
||||
},
|
||||
"ValidationRuleDto": [],
|
||||
"ColumnStylingDto": [],
|
||||
"PermissionDto": {
|
||||
"Deny": false,
|
||||
"C": "App.Prc.PurchaseOrderQuote.Create",
|
||||
"R": "App.Prc.PurchaseOrderQuote",
|
||||
"U": "App.Prc.PurchaseOrderQuote.Update",
|
||||
"E": true,
|
||||
"I": true
|
||||
},
|
||||
"CanRead": false,
|
||||
"CanCreate": false,
|
||||
"CanUpdate": false,
|
||||
"CanExport": false,
|
||||
"DefaultValue": null,
|
||||
"DefaultValueType": 0,
|
||||
"PivotSettingsDto": {
|
||||
"IsPivot": true,
|
||||
"Expanded": false,
|
||||
"SortOrder": "asc",
|
||||
"Area": "filter",
|
||||
"Format": null,
|
||||
"SummaryType": null,
|
||||
"GroupInterval": "",
|
||||
"WordWrapEnabled": false
|
||||
},
|
||||
"Alignment": null,
|
||||
"Format": null,
|
||||
"EditOrderNo": 4,
|
||||
"EditGroupOrderNo": 1,
|
||||
"EditorType2": "dxSelectBox",
|
||||
"ColSpan": 1,
|
||||
"EditorOptions": "{\"showClearButton\":true,\"searchEnabled\":true}",
|
||||
"EditorOptions": "{\"type\":\"date\",\"displayFormat\":\"dd.MM.yyyy\",\"useMaskBehavior\":true,\"showClearButton\":true}",
|
||||
"GridBoxOptions": null,
|
||||
"TagBoxOptions": null,
|
||||
"ImageUploadOptions": null,
|
||||
|
|
@ -1349,26 +1200,19 @@
|
|||
"IsCreatedField": true,
|
||||
"InsertedRecords": {
|
||||
"LanguageKeys": [
|
||||
"App.Prc.PurchaseOrderQuote",
|
||||
"App.Prc.PurchaseOrderQuote.Title",
|
||||
"App.Prc.PurchaseOrderQuote.Desc",
|
||||
"App.Prc.SupplierResponse.Waiting",
|
||||
"App.Prc.SupplierResponse.Quoted",
|
||||
"App.Prc.SupplierResponse.NotQuoted",
|
||||
"App.Listform.ListformField.SupplierResponse",
|
||||
"App.Listform.ListformField.QuoteValidUntil",
|
||||
"App.Listform.ListformField.QuoteDate",
|
||||
"App.Listform.ListformField.QuotedByUserId"
|
||||
"App.Prc.PurchaseRfqQuote",
|
||||
"App.Prc.PurchaseRfqQuote.Title",
|
||||
"App.Prc.PurchaseRfqQuote.Desc"
|
||||
],
|
||||
"PermissionGroupNames": [],
|
||||
"PermissionNames": [
|
||||
"App.Prc.PurchaseOrderQuote",
|
||||
"App.Prc.PurchaseOrderQuote.Create",
|
||||
"App.Prc.PurchaseOrderQuote.Update",
|
||||
"App.Prc.PurchaseOrderQuote.Delete",
|
||||
"App.Prc.PurchaseOrderQuote.Export",
|
||||
"App.Prc.PurchaseOrderQuote.Import",
|
||||
"App.Prc.PurchaseOrderQuote.Note"
|
||||
"App.Prc.PurchaseRfqQuote",
|
||||
"App.Prc.PurchaseRfqQuote.Create",
|
||||
"App.Prc.PurchaseRfqQuote.Update",
|
||||
"App.Prc.PurchaseRfqQuote.Delete",
|
||||
"App.Prc.PurchaseRfqQuote.Export",
|
||||
"App.Prc.PurchaseRfqQuote.Import",
|
||||
"App.Prc.PurchaseRfqQuote.Note"
|
||||
],
|
||||
"MenuCodes": [],
|
||||
"DataSourceCodes": [],
|
||||
|
|
@ -996,8 +996,10 @@ function ScriptBuilderDialog({
|
|||
variant="solid"
|
||||
icon={<FaCheck />}
|
||||
onClick={() => {
|
||||
// Sihirbazda kurala dokunulmadiysa kurallardan uretilen metin elle yazilmis kodun
|
||||
// yerine gecmez; aksi halde basliksiz script bos metinle silinirdi.
|
||||
const script =
|
||||
view === 'wizard'
|
||||
view === 'wizard' && (wizardTouched.current || !codeDiverged)
|
||||
? generatedScript
|
||||
: staleHeader
|
||||
? code.trim().split('\n').slice(1).join('\n').trim()
|
||||
|
|
|
|||
|
|
@ -280,7 +280,8 @@ export interface ColumnHeaderDto {
|
|||
export interface ColumnStylingDto {
|
||||
rowType?: ColumnRowTypeListOptions
|
||||
useRow: boolean
|
||||
condition?: ColumnValidationComparisonTypeEnum
|
||||
/** Runtime operatörü (`controlStyleCondition`): = <> < <= > >= contains … between anyof noneof */
|
||||
condition?: string
|
||||
conditionValue?: string
|
||||
cssStyles?: string
|
||||
cssClassName?: string
|
||||
|
|
@ -709,7 +710,8 @@ export interface GridPagerOptionDto {
|
|||
infoText?: string
|
||||
displayMode?: PagerDisplayMode
|
||||
scrollingMode?: ScrollMode | 'virtual'
|
||||
loadPanelEnabled?: boolean | 'auto'
|
||||
/** Sunucu metin olarak gönderir: 'auto' | 'true' | 'false' */
|
||||
loadPanelEnabled?: boolean | 'auto' | 'true' | 'false'
|
||||
loadPanelText?: string
|
||||
}
|
||||
|
||||
|
|
@ -790,6 +792,8 @@ export interface ValidationRuleDto {
|
|||
ignoreEmptyValue: boolean
|
||||
reevaluate: boolean
|
||||
comparisonType?: ColumnValidationComparisonTypeEnum
|
||||
comparisonTarget?: string
|
||||
validationCallback?: string
|
||||
pattern?: string
|
||||
max: Date | number
|
||||
min: Date | number
|
||||
|
|
@ -805,7 +809,10 @@ export interface SubFormDto {
|
|||
|
||||
tabMode: RowMode
|
||||
searchParams: URLSearchParams
|
||||
id?: string
|
||||
/** Form sekmesinin kaydını seçen ilişki koşulu: [ChildFieldName, '=', üst değer] */
|
||||
relationFilter?: [string, string, unknown]
|
||||
/** Form sekmesinde yeni kayda yazılacak ilişki alanı (ChildFieldName → üst değer) */
|
||||
relationParams?: URLSearchParams
|
||||
}
|
||||
|
||||
export interface SubFormRelationDto {
|
||||
|
|
|
|||
|
|
@ -23,27 +23,23 @@ import { Field, Form, Formik } from 'formik'
|
|||
import { useState } from 'react'
|
||||
import { FaEdit, FaPlusSquare, FaCheck, FaTrashAlt } from 'react-icons/fa'
|
||||
import { object, string } from 'yup'
|
||||
import { columnRowTypeListOptions, columnValidationComparisonTypeListOptions } from '../options'
|
||||
import { columnRowTypeListOptions, columnStylingConditionOptions } from '../options'
|
||||
import { FormFieldEditProps } from './FormFields'
|
||||
import { getListFormFieldById } from '@/services/admin/list-form-field.service'
|
||||
import {
|
||||
ColumnRowTypeListOptions,
|
||||
ColumnStylingDto,
|
||||
ColumnValidationComparisonTypeEnum,
|
||||
} from '@/proxy/form/models'
|
||||
import { ColumnRowTypeListOptions, ColumnStylingDto } from '@/proxy/form/models'
|
||||
import SelectField from '../shared/SelectField'
|
||||
import { useFieldPermission } from './useFieldPermission'
|
||||
|
||||
const NewItem: ColumnStylingDto = {
|
||||
rowType: ColumnRowTypeListOptions.Data,
|
||||
useRow: false,
|
||||
condition: ColumnValidationComparisonTypeEnum.None,
|
||||
condition: '=',
|
||||
}
|
||||
|
||||
const schema = object().shape({
|
||||
rowType: string().required(),
|
||||
condition: string().required(),
|
||||
conditionValue: string().required(),
|
||||
conditionValue: string(),
|
||||
})
|
||||
|
||||
function FormFieldTabConditionalFormatting({
|
||||
|
|
@ -253,7 +249,7 @@ function FormFieldTabConditionalFormatting({
|
|||
>
|
||||
<SelectField
|
||||
name="condition"
|
||||
options={columnValidationComparisonTypeListOptions}
|
||||
options={columnStylingConditionOptions}
|
||||
isClearable={false}
|
||||
/>
|
||||
</FormItem>
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ const schema = object().shape({
|
|||
ignoreEmptyValue: bool(),
|
||||
reevaluate: bool(),
|
||||
comparisonType: string().oneOf(Object.values(ColumnValidationComparisonTypeEnum) as string[]),
|
||||
comparisonTarget: string(),
|
||||
validationCallback: string(),
|
||||
pattern: string(),
|
||||
max: string(),
|
||||
min: string(),
|
||||
|
|
@ -287,6 +289,34 @@ function FormFieldTabValidationRules({
|
|||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="Comparison Target"
|
||||
invalid={errors.comparisonTarget && touched.comparisonTarget}
|
||||
errorMessage={errors.comparisonTarget}
|
||||
>
|
||||
<Field
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
name="comparisonTarget"
|
||||
placeholder="FieldName"
|
||||
component={Input}
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="Validation Callback"
|
||||
invalid={errors.validationCallback && touched.validationCallback}
|
||||
errorMessage={errors.validationCallback}
|
||||
>
|
||||
<Field
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
name="validationCallback"
|
||||
placeholder="(e) => e.value > 0"
|
||||
component={Input}
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label="Pattern"
|
||||
invalid={errors.pattern && touched.pattern}
|
||||
|
|
|
|||
|
|
@ -373,12 +373,13 @@ export const recipes: Recipe[] = [
|
|||
},
|
||||
],
|
||||
build: ({ params }) => {
|
||||
const offset = Number(params.offset) || 0
|
||||
// Gün sayısı tam sayıdır; C# (EditorScriptRule) aynı kırpmayı yapar.
|
||||
const offset = Math.trunc(Number(params.offset)) || 0
|
||||
const base = offset ? `new Date(Date.now() + ${offset} * 86400000)` : 'new Date()'
|
||||
return `set(${q(params.target)}, ${base}.toISOString().slice(0, 10))`
|
||||
},
|
||||
describe: ({ params }, t) => {
|
||||
const offset = Number(params.offset) || 0
|
||||
const offset = Math.trunc(Number(params.offset)) || 0
|
||||
const when =
|
||||
offset > 0
|
||||
? t('::App.ScriptBuilderWord.DaysLater', { count: offset })
|
||||
|
|
|
|||
|
|
@ -499,6 +499,12 @@ export const columnValidationComparisonTypeListOptions = enumToList<string>(
|
|||
ColumnValidationComparisonTypeEnum,
|
||||
)
|
||||
export const columnRowTypeListOptions = enumToList<string>(ColumnRowTypeListOptions)
|
||||
// Kosullu bicimin runtime'da tanidigi operatorler (controlStyleCondition); dogrulama
|
||||
// karsilastirmalari (==, !==) burada calismaz.
|
||||
export const columnStylingConditionOptions = [
|
||||
...enumToList<string>(ColumnCascadeFilterOperatorEnum),
|
||||
...enumToList<string>({ anyof: 'anyof', noneof: 'noneof' }),
|
||||
]
|
||||
export const commandButtonPositionTypeOptions = enumToList(UiCommandButtonPositionTypeEnum)
|
||||
export const tabTypeOptions = enumToList<string>(SubFormTabTypeEnum)
|
||||
export const cascadeFilterOperator = enumToList<string>(ColumnCascadeFilterOperatorEnum)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { FormPageShell } from './shared/FormPageShell'
|
|||
|
||||
const FormEdit = (props: FormProps = { isSubForm: false }) => {
|
||||
const mode = 'edit'
|
||||
const { isSubForm, level, onActionView, onActionNew } = props
|
||||
const { isSubForm, level, relationFilter, onActionView, onActionNew } = props
|
||||
const params = useParams()
|
||||
const listFormCode = props?.listFormCode ?? params?.listFormCode ?? ''
|
||||
const id = props?.id ?? params?.id ?? ''
|
||||
|
|
@ -32,11 +32,15 @@ const FormEdit = (props: FormProps = { isSubForm: false }) => {
|
|||
mode,
|
||||
listFormCode,
|
||||
id,
|
||||
relationFilter,
|
||||
level,
|
||||
isSubForm,
|
||||
onSubmitAction: onActionView,
|
||||
})
|
||||
|
||||
// İlişkiyle açılan alt form kaydında anahtar veriden okunur.
|
||||
const recordId = formData?.[gridDto?.gridOptions.keyFieldName ?? 'Id'] || id
|
||||
|
||||
return (
|
||||
<FormPageShell
|
||||
mode={mode}
|
||||
|
|
@ -49,7 +53,7 @@ const FormEdit = (props: FormProps = { isSubForm: false }) => {
|
|||
formItems={formItems}
|
||||
refForm={refForm}
|
||||
setFormData={setFormData}
|
||||
noteEntityId={id}
|
||||
noteEntityId={recordId}
|
||||
actions={
|
||||
permissionResults && (
|
||||
<FormButtons
|
||||
|
|
@ -68,7 +72,7 @@ const FormEdit = (props: FormProps = { isSubForm: false }) => {
|
|||
permissions={permissionResults}
|
||||
handleSubmit={handleSubmit}
|
||||
refreshData={fetchData}
|
||||
getSelectedRowKeys={() => [id]}
|
||||
getSelectedRowKeys={() => [recordId]}
|
||||
getSelectedRowsData={() => [formData]}
|
||||
getFilter={() => filter}
|
||||
onActionView={onActionView}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { FormPageShell } from './shared/FormPageShell'
|
|||
|
||||
const FormView = (props: FormProps = { isSubForm: false }) => {
|
||||
const mode = 'view'
|
||||
const { isSubForm, level, onActionEdit, onActionNew } = props
|
||||
const { isSubForm, level, relationFilter, onActionEdit, onActionNew } = props
|
||||
const params = useParams()
|
||||
const listFormCode = props?.listFormCode ?? params?.listFormCode ?? ''
|
||||
const id = props?.id ?? params?.id ?? ''
|
||||
|
|
@ -26,7 +26,7 @@ const FormView = (props: FormProps = { isSubForm: false }) => {
|
|||
previewFieldOrder,
|
||||
saveFieldOrder,
|
||||
canStoreFieldOrder,
|
||||
} = useGridData({ mode, listFormCode, id, isSubForm })
|
||||
} = useGridData({ mode, listFormCode, id, relationFilter, isSubForm })
|
||||
|
||||
// Form tipi liste formları ID olmadan da açılabildiği için kayıt anahtarı
|
||||
// veriden okunur.
|
||||
|
|
|
|||
|
|
@ -95,7 +95,10 @@ const withParentRelation = (subForm: SubFormDto, formData: any): SubFormDto => {
|
|||
return {
|
||||
...subForm,
|
||||
searchParams: new URLSearchParams({ filter: JSON.stringify(filter) }),
|
||||
id: formData[relation.parentFieldName],
|
||||
relationFilter: filter,
|
||||
relationParams: new URLSearchParams({
|
||||
[relation.childFieldName]: String(formData[relation.parentFieldName]),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -191,7 +194,8 @@ const SubForms = (props: {
|
|||
return (
|
||||
<FormEdit
|
||||
{...commonProps}
|
||||
id={subForm.id}
|
||||
id=""
|
||||
relationFilter={subForm.relationFilter}
|
||||
onActionNew={() => setTabMode(subForm.code, 'new')}
|
||||
onActionView={() => setTabMode(subForm.code, 'view')}
|
||||
/>
|
||||
|
|
@ -202,7 +206,7 @@ const SubForms = (props: {
|
|||
return (
|
||||
<FormNew
|
||||
{...commonProps}
|
||||
sParams={subForm.searchParams}
|
||||
sParams={subForm.relationParams}
|
||||
onActionView={() => setTabMode(subForm.code, 'view')}
|
||||
/>
|
||||
)
|
||||
|
|
@ -211,7 +215,8 @@ const SubForms = (props: {
|
|||
return (
|
||||
<FormView
|
||||
{...commonProps}
|
||||
id={subForm.id}
|
||||
id=""
|
||||
relationFilter={subForm.relationFilter}
|
||||
onActionNew={() => setTabMode(subForm.code, 'new')}
|
||||
onActionEdit={() => setTabMode(subForm.code, 'edit')}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
* ayrı ayrı tanımlıydı.
|
||||
*/
|
||||
import { captionize } from 'devextreme/core/utils/inflector'
|
||||
import type { ValidationRule } from 'devextreme/common'
|
||||
import type { GroupItem } from 'devextreme/ui/form'
|
||||
import type { ColumnFormatDto, GridDto } from '@/proxy/form/models'
|
||||
import { getEditingFormGroups } from '../../list/Utils'
|
||||
|
|
@ -16,6 +15,7 @@ import {
|
|||
withEditorTypeDefaults,
|
||||
} from '../../list/shared/editingForm'
|
||||
import { getCascadeParentFieldsOf } from '../../list/shared/cascade'
|
||||
import { toValidationRules } from '../../list/shared/validationRules'
|
||||
import type { GridColumnData } from '../../list/GridColumnData'
|
||||
import type { RowMode, SimpleItemWithColData } from '../types'
|
||||
|
||||
|
|
@ -44,6 +44,7 @@ type BuildFormItemsParams = {
|
|||
formData: any
|
||||
/** Kullanıcının kaydettiği alan sırası (alan adı → grup içi sıra); yoksa `editOrderNo`. */
|
||||
fieldOrder?: FormFieldOrder
|
||||
translate: (key: string) => string
|
||||
}
|
||||
|
||||
/** Form sayfasının kullanıcı bazlı alan sırası; ListForm state'inde `form-{storageKey}` adıyla saklanır. */
|
||||
|
|
@ -68,6 +69,7 @@ const toFormItem = (
|
|||
columns,
|
||||
getLookupDataSource,
|
||||
formData,
|
||||
translate,
|
||||
}: Omit<BuildFormItemsParams, 'gridDto' | 'fieldOrder'>,
|
||||
): SimpleItemWithColData => {
|
||||
let parsedEditorOptions: Record<string, any> = {}
|
||||
|
|
@ -131,11 +133,11 @@ const toFormItem = (
|
|||
colFormat.validationRuleDto?.some((rule) => rule.type === 'required'),
|
||||
) ?? false
|
||||
|
||||
// Grid popup'ı kuralları kolondan alır; form sayfasında zorunluluk isRequired ile, diğer kurallar
|
||||
// (pattern, email, stringLength…) item üzerinden çalışır.
|
||||
const otherRules = colFormat.validationRuleDto?.filter((rule) => rule.type !== 'required')
|
||||
if (otherRules?.length) {
|
||||
item.validationRules = otherRules as ValidationRule[]
|
||||
// Grid popup'ı kuralları kolondan alır; form sayfasında zorunluluk isRequired ile işaretlenir.
|
||||
// Mesajı olan zorunluluk kuralı da item'a geçer, yoksa özel mesaj düşerdi.
|
||||
const rules = colFormat.validationRuleDto?.filter((rule) => rule.type !== 'required' || rule.message)
|
||||
if (rules?.length) {
|
||||
item.validationRules = toValidationRules(rules, translate)
|
||||
}
|
||||
|
||||
return item
|
||||
|
|
@ -153,6 +155,7 @@ export const buildFormGroupItems = ({
|
|||
getLookupDataSource,
|
||||
formData,
|
||||
fieldOrder,
|
||||
translate,
|
||||
}: BuildFormItemsParams): GroupItem[] =>
|
||||
getEditingFormGroups(gridDto).map(
|
||||
(group: any) =>
|
||||
|
|
@ -163,7 +166,7 @@ export const buildFormGroupItems = ({
|
|||
caption: group.caption,
|
||||
items: sortByFieldOrder<ColumnFormatDto>(group.items ?? [], fieldOrder)
|
||||
.map((colFormat: ColumnFormatDto) =>
|
||||
toFormItem(colFormat, { mode, columns, getLookupDataSource, formData }),
|
||||
toFormItem(colFormat, { mode, columns, getLookupDataSource, formData, translate }),
|
||||
)
|
||||
.filter((item) => isFormItemVisible(item, mode)),
|
||||
}) as GroupItem,
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ export interface FormProps extends Meta {
|
|||
level?: number
|
||||
isSubForm?: boolean
|
||||
id?: string
|
||||
/** Alt form sekmesi: kayıt anahtar yerine ilişki alanıyla seçilir (Id → Id dışındaki ilişkiler). */
|
||||
relationFilter?: [string, string, unknown]
|
||||
onActionEdit?: () => void
|
||||
onActionNew?: () => void
|
||||
onActionView?: () => void
|
||||
|
|
|
|||
|
|
@ -29,11 +29,12 @@ const useGridData = (props: {
|
|||
mode: RowMode
|
||||
listFormCode: string
|
||||
id?: string
|
||||
relationFilter?: [string, string, unknown]
|
||||
level?: number
|
||||
isSubForm?: boolean
|
||||
onSubmitAction?: () => void
|
||||
}) => {
|
||||
const { mode, listFormCode, id, isSubForm } = props
|
||||
const { mode, listFormCode, id, relationFilter, isSubForm } = props
|
||||
|
||||
const [gridReady, setGridReady] = useState(false)
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
|
@ -156,8 +157,10 @@ const useGridData = (props: {
|
|||
}
|
||||
finishSubmit(getFormRecordUrl(listFormCode, newId))
|
||||
} else if (mode === 'edit') {
|
||||
await dataSource.update(id, buildUpdateData(formValues))
|
||||
finishSubmit(getFormRecordUrl(listFormCode, id))
|
||||
// İlişkiyle açılan alt form kaydında anahtar URL'de değil yüklenen kayıttadır.
|
||||
const recordKey = (keyFieldName && formDataOld?.[keyFieldName]) || id
|
||||
await dataSource.update(recordKey, buildUpdateData(formValues))
|
||||
finishSubmit(getFormRecordUrl(listFormCode, recordKey))
|
||||
}
|
||||
} catch (error: any) {
|
||||
toast.push(<Notification title={error.message} type="danger" />, {
|
||||
|
|
@ -227,6 +230,7 @@ const useGridData = (props: {
|
|||
getLookupDataSource,
|
||||
formData,
|
||||
fieldOrder: savedOrder,
|
||||
translate,
|
||||
}),
|
||||
)
|
||||
setGridReady(true)
|
||||
|
|
@ -252,6 +256,7 @@ const useGridData = (props: {
|
|||
getLookupDataSource,
|
||||
formData: currentFormDataRef.current,
|
||||
fieldOrder: order,
|
||||
translate,
|
||||
}),
|
||||
)
|
||||
},
|
||||
|
|
@ -360,7 +365,9 @@ const useGridData = (props: {
|
|||
useEffect(() => {
|
||||
if (!gridReady || mode === 'new') return
|
||||
|
||||
if (id) {
|
||||
if (relationFilter) {
|
||||
setFilter(relationFilter)
|
||||
} else if (id) {
|
||||
setFilter([gridDto?.gridOptions.keyFieldName ?? 'Id', '=', id])
|
||||
} else {
|
||||
// Form tipi liste formlar ID olmadan açılabilir; kayıt seçimi sunucudaki
|
||||
|
|
@ -368,7 +375,7 @@ const useGridData = (props: {
|
|||
fetchData()
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [id, gridReady])
|
||||
}, [id, JSON.stringify(relationFilter ?? null), gridReady])
|
||||
|
||||
useEffect(() => {
|
||||
if (filter?.length) {
|
||||
|
|
|
|||
|
|
@ -125,9 +125,9 @@ const createLookupApiDataSource = (
|
|||
method = 'GET',
|
||||
url = '',
|
||||
bodyTemplate = '',
|
||||
keySelector = 'a=>a.id',
|
||||
nameSelector = 'a=>a.name',
|
||||
groupSelector = 'a=>a.group',
|
||||
keySelector,
|
||||
nameSelector,
|
||||
groupSelector,
|
||||
] = lookupQuery.split(';')
|
||||
|
||||
// Gövdedeki @param0, @param1… yer tutucularını cascade filtreleriyle doldur.
|
||||
|
|
@ -144,14 +144,10 @@ const createLookupApiDataSource = (
|
|||
if (!data) return []
|
||||
if (!Array.isArray(data)) data = [data]
|
||||
|
||||
// NOT: Selector'lar `a=>a.id` biçiminde yapılandırmadan gelir; bu yüzden
|
||||
// map parametresi `a` olarak adlandırılmalıdır. Önceden parametresiz
|
||||
// `() => ...` kullanıldığı için eval fonksiyonun kendisini döndürüyor ve
|
||||
// key/name/group alanları bozuk geliyordu.
|
||||
return data.map((a: any) => ({
|
||||
key: eval(keySelector),
|
||||
name: eval(nameSelector),
|
||||
group: eval(groupSelector),
|
||||
key: selectLookupValue(a, keySelector, 'a.id'),
|
||||
name: selectLookupValue(a, nameSelector, 'a.name'),
|
||||
group: selectLookupValue(a, groupSelector, 'a.group'),
|
||||
|
||||
...a,
|
||||
}))
|
||||
|
|
@ -163,6 +159,13 @@ const createLookupApiDataSource = (
|
|||
},
|
||||
})
|
||||
|
||||
// Seçici satır `a` üzerinde çalışan bir ifadedir (`a.id`); `a => a.id` biçimi de kabul edilir.
|
||||
// Eksik ya da boş parça varsayılana düşer, `null` alanı boş bırakır.
|
||||
const selectLookupValue = (a: any, selector: string | undefined, fallback: string) => {
|
||||
const result = eval(selector?.trim() || fallback)
|
||||
return typeof result === 'function' ? result(a) : result
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup kolonunun veri kaynağı. Grid/Tree/Card (`useListFormColumns`) ve Form aynı kuralı
|
||||
* kullanır; `rowData` cascade ebeveynlerinin okunduğu kayıttır.
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ import {
|
|||
extractSearchParamsFields,
|
||||
getEditingFormGroups,
|
||||
GridExtraFilterState,
|
||||
resolveLoadPanelEnabled,
|
||||
safeJsonParse,
|
||||
} from './Utils'
|
||||
import {
|
||||
|
|
@ -1369,7 +1370,7 @@ const CardView = (props: CardViewProps) => {
|
|||
mode={gridDto.gridOptions.columnOptionDto?.columnChooserMode}
|
||||
/>
|
||||
<LoadPanel
|
||||
visible={gridDto.gridOptions.pagerOptionDto?.loadPanelEnabled !== false}
|
||||
visible={resolveLoadPanelEnabled(gridDto.gridOptions.pagerOptionDto?.loadPanelEnabled) !== false}
|
||||
message={gridDto.gridOptions.pagerOptionDto?.loadPanelText}
|
||||
/>
|
||||
</DxCardView>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,11 @@ import { object, array, string } from 'yup'
|
|||
import { SummaryTypeEnum } from '@/proxy/form/models'
|
||||
import { useState, useEffect } from 'react'
|
||||
|
||||
|
||||
// Seri tipi DevExtreme değeriyle (`fullstackedbar`) saklanır; eski kayıtlarda etiket yazılmış olabilir.
|
||||
const findChartSeriesType = (value?: string) =>
|
||||
chartSeriesTypeOptions.find((t) => t.value === value || t.label === value)
|
||||
|
||||
interface ChartDrawerProps {
|
||||
open: boolean
|
||||
onClose: () => void
|
||||
|
|
@ -225,14 +230,10 @@ const ChartDrawer = ({
|
|||
className="w-full px-3 py-2 text-left border border-gray-300 rounded bg-white hover:bg-gray-50 flex items-center gap-2 transition-colors dark:border-gray-600 dark:bg-gray-900 dark:hover:bg-gray-800"
|
||||
>
|
||||
<span className="text-xl">
|
||||
{chartSeriesTypeOptions.find(
|
||||
(t) => t.label === field.value,
|
||||
)?.icon || '📊'}
|
||||
{findChartSeriesType(field.value)?.icon || '📊'}
|
||||
</span>
|
||||
<span className="text-sm font-medium">
|
||||
{chartSeriesTypeOptions.find(
|
||||
(t) => t.label === field.value,
|
||||
)?.label || field.value}
|
||||
{findChartSeriesType(field.value)?.label || field.value}
|
||||
</span>
|
||||
</Button>
|
||||
{selectedSeriesIndex === index && (
|
||||
|
|
@ -243,11 +244,11 @@ const ChartDrawer = ({
|
|||
key={chartType.label}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
form.setFieldValue(field.name, chartType.label)
|
||||
form.setFieldValue(field.name, chartType.value)
|
||||
setSelectedSeriesIndex(-1)
|
||||
}}
|
||||
className={`p-2 rounded-lg hover:bg-blue-50 flex items-center gap-2 transition-all dark:hover:bg-blue-900/30 ${
|
||||
field.value === chartType.label
|
||||
findChartSeriesType(field.value) === chartType
|
||||
? 'bg-blue-100 ring-2 ring-blue-400 dark:bg-blue-900/40 dark:ring-blue-500'
|
||||
: 'bg-gray-50 dark:bg-gray-800'
|
||||
}`}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ import {
|
|||
} from './shared/hooks'
|
||||
import { startWorkflowForInsertedRow } from './shared/workflowRows'
|
||||
import { cancelOnTemplateEditorErrors } from './shared/templateEditorValidation'
|
||||
import { resolveLoadPanelEnabled } from './Utils'
|
||||
|
||||
interface GridProps {
|
||||
listFormCode: string
|
||||
|
|
@ -720,7 +721,7 @@ const Grid = (props: GridProps) => {
|
|||
<ColumnFixing enabled={gridOptions.columnOptionDto?.columnFixingEnabled} />
|
||||
<Scrolling mode={gridOptions.pagerOptionDto?.scrollingMode} />
|
||||
<LoadPanel
|
||||
enabled={gridOptions.pagerOptionDto?.loadPanelEnabled}
|
||||
enabled={resolveLoadPanelEnabled(gridOptions.pagerOptionDto?.loadPanelEnabled)}
|
||||
text={gridOptions.pagerOptionDto?.loadPanelText}
|
||||
/>
|
||||
<Summary>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import type { Field } from 'devextreme/ui/pivot_grid/data_source'
|
|||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import PageTitle from '@/components/shared/PageTitle'
|
||||
import { GridColumnData } from './GridColumnData'
|
||||
import { pivotFieldConvertDataType, setGridPanelColor } from './Utils'
|
||||
import { pivotFieldConvertDataType, resolveLoadPanelEnabled, setGridPanelColor } from './Utils'
|
||||
import { createConditionalCellStyleHandler } from './shared/cellStyles'
|
||||
import { useListFormCustomSources, useListFormGridDto } from './shared/hooks'
|
||||
import { exportPivotView } from './shared/exportListView'
|
||||
|
|
@ -472,7 +472,7 @@ const Pivot = (props: PivotProps) => {
|
|||
/>
|
||||
<LoadPanel
|
||||
enabled={
|
||||
gridDto.gridOptions.pagerOptionDto?.loadPanelEnabled as boolean | undefined
|
||||
resolveLoadPanelEnabled(gridDto.gridOptions.pagerOptionDto?.loadPanelEnabled) !== false
|
||||
}
|
||||
text={gridDto.gridOptions.pagerOptionDto?.loadPanelText}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -818,7 +818,7 @@ const SchedulerView = (props: SchedulerViewProps) => {
|
|||
recurrenceExceptionExpr={
|
||||
gridDto.gridOptions.schedulerOptionDto?.recurrenceExceptionExpr
|
||||
}
|
||||
startDayHour={gridDto.gridOptions.schedulerOptionDto?.startDayHour || 8}
|
||||
startDayHour={gridDto.gridOptions.schedulerOptionDto?.startDayHour ?? 8}
|
||||
endDayHour={gridDto.gridOptions.schedulerOptionDto?.endDayHour || 20}
|
||||
currentView={currentView}
|
||||
onCurrentViewChange={onCurrentViewChange}
|
||||
|
|
@ -854,7 +854,7 @@ const SchedulerView = (props: SchedulerViewProps) => {
|
|||
cellDuration={gridDto.gridOptions.schedulerOptionDto?.cellDuration || 30}
|
||||
firstDayOfWeek={
|
||||
(gridDto.gridOptions.schedulerOptionDto?.firstDayOfWeek as
|
||||
0 | 1 | 2 | 3 | 4 | 5 | 6) || 1
|
||||
0 | 1 | 2 | 3 | 4 | 5 | 6) ?? 1
|
||||
}
|
||||
adaptivityEnabled={false}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ import {
|
|||
} from './shared/hooks'
|
||||
import { startWorkflowForInsertedRow } from './shared/workflowRows'
|
||||
import { cancelOnTemplateEditorErrors } from './shared/templateEditorValidation'
|
||||
import { resolveLoadPanelEnabled } from './Utils'
|
||||
|
||||
interface TreeProps {
|
||||
listFormCode: string
|
||||
|
|
@ -704,7 +705,7 @@ const Tree = (props: TreeProps) => {
|
|||
<ColumnFixing enabled={gridOptions.columnOptionDto?.columnFixingEnabled} />
|
||||
<Scrolling mode={gridOptions.pagerOptionDto?.scrollingMode} />
|
||||
<LoadPanel
|
||||
enabled={gridOptions.pagerOptionDto?.loadPanelEnabled}
|
||||
enabled={resolveLoadPanelEnabled(gridOptions.pagerOptionDto?.loadPanelEnabled)}
|
||||
text={gridOptions.pagerOptionDto?.loadPanelText}
|
||||
/>
|
||||
</TreeListDx>
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue