Both sides previous revisionПредходна версияСледваща версия | Предходна версия |
kak_da:spravki_scriptove [2019/01/02 15:30] – [Свойства на колони в динамични справки] t.lalova | kak_da:spravki_scriptove [2020/07/31 10:59] (текуща) – [Системна процедура SYS$SLEEP] t.lalova |
---|
| |
begin | begin |
------- ЗАРЕЖДЕАНЕ НА ПРЕВОДИ -------------- | ------- ЗАРЕЖДАНЕ НА ПРЕВОДИ -------------- |
LANG_1=null; -- LANG_1 в config е not null, така че тук инициализацията е само за красота | LANG_1=null; -- LANG_1 в config е not null, така че тук инициализацията е само за красота |
LANG_2=null; | LANG_2=null; |
2. Всичко трябва да е заградено в <FieldProperties> ... </FieldProperties> \\ | 2. Всичко трябва да е заградено в <FieldProperties> ... </FieldProperties> \\ |
3. Какво свойства има: \\ | 3. Какво свойства има: \\ |
- name - име на поле | * name - име на поле |
- displaylabel - Наименование на полето в таблицата (изгледа) - използва се "|" за създаване на бандове | * displaylabel - Наименование на полето в таблицата (изгледа) - използва се "|" за създаване на бандове |
- displaywidth - Размер на полето в таблицата (цяло число) | * displaywidth - Размер на полето в таблицата (цяло число) |
- readonly - Ако "false" - полето ще е разрешено за редакция (дефолт не е разрешено) | * readonly - Ако "false" - полето ще е разрешено за редакция (дефолт не е разрешено) |
- focusing - Ако "true" - полето ще може да се клика върху него (дефолт - не може и зависи от справката дали има поне една колона за редакция!!!) | * focusing - Ако "true" - полето ще може да се клика върху него (дефолт - не може и зависи от справката дали има поне една колона за редакция!!!) |
- visible - Ако е "false" се поставя за скрито (дефолт - полето е видимо) | * visible - Ако е "false" се поставя за скрито (дефолт - полето е видимо) |
- is_checkbox - Ако "true" означава, че полето ще бъде CHECK BOX | * is_checkbox - Ако "true" означава, че полето ще бъде CHECK BOX |
- is_memo - Ако "true" означава, че полето е текст | * is_memo - Ако "true" означава, че полето е текст |
- is_icon_index - Ако "true" означава, че в полето има индекс на икона и ще се визуализира някоя от запазените картинки () | * is_icon_index - Ако "true" означава, че в полето има индекс на икона и ще се визуализира някоя от запазените картинки () |
- is_picture - Ако "true" означава, че полето е снимка | * is_picture - Ако "true" означава, че полето е снимка |
- displayformat - ако има такова свойство се поставя като формат на показване на полето | * displayformat - ако има такова свойство се поставя като формат на показване на полето |
- display_format - аналогично на displayformat | * display_format - аналогично на displayformat |
- group_level - кое ниво на групране е полето (цяло число). Ако има такова свойство се търси и до кое ниво има разпънатост | * group_level - кое ниво на групране е полето (цяло число). Ако има такова свойство се търси и до кое ниво има разпънатост |
- expand_level - до кое ниво да се разпъва - зависи от конкретното поле - очаква "true" | * expand_level - до кое ниво да се разпъва - зависи от конкретното поле - очаква "true" |
- aggregate_type - възможни стойности: SUM, AVG, COUNT, MIN, MAX | * aggregate_type - възможни стойности: SUM, AVG, COUNT, MIN, MAX |
- aggregate_postion - Основните са 1, 2 и 4. 1 - Поставя се в Тотала, 2 - поставя се и в Колонтитула по групи , 4 - поставя се в заглавието на групите (трябва да има групиране поне на 1 ниво!!!) | * aggregate_postion - Основните са 1, 2 и 4. 1 - Поставя се в Тотала, 2 - поставя се и в Колонтитула по групи , 4 - поставя се в заглавието на групите (трябва да има групиране поне на 1 ниво!!!). 1 - TOTAL, 2 - GROUP TOTAL, 3 - GROUP TOTAL & TOTAL 4 - GROUP HEADER, 5 - 1 + 4, 6 - 2 + 4, 7 - 1 + 2 + 4 |
1 - TOTAL, 2 - GROUP TOTAL, 3 - GROUP TOTAL & TOTAL 4 - GROUP HEADER, 5 - 1 + 4, 6 - 2 + 4, 7 - 1 + 2 + 4 | * freezing - очаква "LEFT" ("1") или "RIGHT" ("2") |
- freezing - очаква "LEFT" ("1") или "RIGHT" ("2") | |
| |
Забележка ("false" може да се заменя с "0", а "true" с "1") | Забележка ("false" може да се заменя с "0", а "true" с "1") |
| |
Примери: | Примери: \\ |
Дейтасет с Колони (по ТД): GROUP_LEVEL_1, GROUP_LEVEL_2, GROUP_LEVEL_3, ITEM_NAME, VALUE_WITH_VAT, FOR_PAY_CHK, PAY_SUM | Дейтасет с Колони (по ТД): GROUP_LEVEL_1, GROUP_LEVEL_2, GROUP_LEVEL_3, ITEM_NAME, VALUE_WITH_VAT, FOR_PAY_CHK, PAY_SUM \\ |
Искаме да групираме по GROUP_LEVEL_1 и да сложим сума на двете числови полета | Искаме да групираме по GROUP_LEVEL_1 и да сложим сума на двете числови полета \\ |
<FieldProperties> | <code xml> |
<field name="GROUP_LEVEL_1" group_level="1" displaylabel="Група|Ниво 1"/> | <FieldProperties> \\ |
<field name="GROUP_LEVEL_2" displaylabel="Група|Ниво 2"/> | <field name="GROUP_LEVEL_1" group_level="1" displaylabel="Група|Ниво 1"/> \\ |
<field name="GROUP_LEVEL_3" displaylabel="Група|Ниво 3"/> | <field name="GROUP_LEVEL_2" displaylabel="Група|Ниво 2"/> \\ |
<field name="ITEM_NAME" displaylabel="Позиция|Наименование"/> | <field name="GROUP_LEVEL_3" displaylabel="Група|Ниво 3"/> \\ |
<field name="VALUE_WITH_VAT" displayformat="0,.00" displaylabel="Документ|Стойност с ДДС" aggregate_type="SUM" aggregate_postion="1"/> | <field name="ITEM_NAME" displaylabel="Позиция|Наименование"/> \\ |
<field name="FOR_PAY_CHK" displaylabel="Документ|За Сторниране">PAY_SUM:=VALUE_WITH_VAT*FOR_PAY_CHK</Field> | <field name="VALUE_WITH_VAT" displayformat="0,.00" displaylabel="Документ|Стойност с ДДС" aggregate_type="SUM" aggregate_postion="1"/> \\ |
<field name="PAY_SUM" displayformat="0,.00" displaylabel="Документ|Сума Сторниране" aggregate_type="SUM" aggregate_postion="1"/> | <field name="FOR_PAY_CHK" displaylabel="Документ|За Сторниране">PAY_SUM:=VALUE_WITH_VAT*FOR_PAY_CHK</Field> \\ |
</FieldProperties> | <field name="PAY_SUM" displayformat="0,.00" displaylabel="Документ|Сума Сторниране" aggregate_type="SUM" aggregate_postion="1"/> \\ |
| </FieldProperties> \\ |
| </code> |
| |
| ===== Системна процедура SYS$SLEEP ===== |
| |
| Функция **SYS$SLEEP** служи за прекъсване на изпълнението на процедура, блок или тригер за определен брой милисекунди. |
| Може да се използва в случай на заключване на записи и изчакване за последващото освобождаване. |
| |
| Пример 1: Използване на процедурата в стейтмънт за извличане на номер от автоматична номерация (кочан). |
| |
| <code pascal> |
| NEW_DOC_NUMBER = null; |
| if (DOC_NUM_GENERATOR_REF is not null) then |
| begin |
| STMT = 'execute block |
| ( |
| WRH_DOC_TYPE_REF DM_REF = :WRH_DOC_TYPE_REF, |
| DOC_NUM_GENERATOR_REF DM_REF = :DOC_NUM_GENERATOR_REF, |
| WRH_DOC_DATE DM_DATE = :WRH_DOC_DATE |
| ) |
| returns |
| ( |
| NEW_DOC_NUMBER DM_REF |
| ) |
| as |
| declare variable MIN_RANGE DM_BIGINT; |
| declare variable MAX_RANGE DM_BIGINT; |
| declare variable CHECK_LAST_INVOICES_DATE DM_INT; |
| declare variable LAST_INVOICE_DATE DM_DATE; |
| declare variable LAST_INVOICE_YEAR DM_INT; |
| declare variable LAST_INVOICE_MONTH DM_INT; |
| declare variable LAST_INVOICE_DAY DM_INT; |
| declare variable repeat_count DM_123; |
| begin |
| MIN_RANGE = null; |
| MAX_RANGE = null; |
| select |
| DNG.RANGE_MIN, DNG.RANGE_MAX |
| from |
| NOM$DOC_NUM_GENERATORS DNG |
| join NOM$DOC_NUM_GENERATOR_TYPES DNGT on DNGT.DOC_NUM_GENERATORS_REF = DNG.ID |
| join CONFIG C on C.CURRENT_COM_ID = DNG.CURRENT_COM_REF |
| where |
| DNG.ID = :DOC_NUM_GENERATOR_REF and |
| DNGT.GENERATOR_DOC_TYPE = :WRH_DOC_TYPE_REF and |
| DNG.GENERATOR_TYPE = 1 |
| into :MIN_RANGE, :MAX_RANGE; |
| |
| repeat_count = 0; |
| NEW_DOC_NUMBER = null; |
| while ((repeat_count < 5) and (NEW_DOC_NUMBER is null)) do |
| begin |
| repeat_count = repeat_count + 1; |
| NEW_DOC_NUMBER = null; |
| update |
| NOM$DOC_NUM_GENERATORS G |
| set |
| G.CURRENT_VALUE = G.CURRENT_VALUE + 1 |
| where |
| G.ID = :DOC_NUM_GENERATOR_REF |
| returning |
| G.CURRENT_VALUE - 1 |
| into |
| :NEW_DOC_NUMBER; |
| when any do |
| begin |
| execute procedure SYS$SLEEP(200); |
| NEW_DOC_NUMBER = null; |
| end |
| end |
| if (NEW_DOC_NUMBER is null) then |
| exception CLEAN_TEXT_ERROR ''There was a problem getting an invoice number for the warehouse document!''; |
| |
| if (((MAX_RANGE is not null) and (NEW_DOC_NUMBER >= MAX_RANGE)) or |
| ((MIN_RANGE is not null) and (NEW_DOC_NUMBER < MIN_RANGE))) then |
| begin |
| -- exausted range of the generator |
| execute procedure SYS$EXCEPTION_CLEAN(64); |
| end |
| |
| CHECK_LAST_INVOICES_DATE = null; |
| select |
| WDT2.CHECK_LAST_INVOICES_DATE |
| from |
| WRH$DOC_TYPES2 WDT2 |
| where |
| WDT2.ID = :WRH_DOC_TYPE_REF |
| into |
| :CHECK_LAST_INVOICES_DATE; |
| |
| if ((CHECK_LAST_INVOICES_DATE is not null) and (CHECK_LAST_INVOICES_DATE > 0)) then |
| begin |
| -- check if the date of the previous invoice is not past the date of the current invoice |
| LAST_INVOICE_DATE = null; |
| select |
| first 1 |
| WD.DOC_DATE, extract(year from WD.DOC_DATE), extract(month from WD.DOC_DATE), |
| extract(day from WD.DOC_DATE) |
| from |
| WRH$DOCS WD |
| where |
| (WD.DOC_NUMBER < :NEW_DOC_NUMBER) and |
| (WD.DOC_NUMBER >= (:NEW_DOC_NUMBER - :CHECK_LAST_INVOICES_DATE)) and |
| (WD.DOC_STATUS >= 0) and |
| (WD.DOC_NUM_GENERATOR_REF = :DOC_NUM_GENERATOR_REF) |
| order by |
| WD.DOC_NUMBER desc |
| into |
| :LAST_INVOICE_DATE, :LAST_INVOICE_YEAR, LAST_INVOICE_MONTH, :LAST_INVOICE_DAY; |
| |
| if ((LAST_INVOICE_DATE is not null) and |
| (LAST_INVOICE_DATE > :WRH_DOC_DATE)) then |
| begin |
| execute procedure SYS$EXCEPTION_CLEAN(71, |
| '' '' || LAST_INVOICE_DAY || ''.'' || LAST_INVOICE_MONTH || ''.'' || LAST_INVOICE_YEAR); |
| end |
| end |
| suspend; |
| end'; |
| |
| |
| execute statement (STMT) (WRH_DOC_TYPE_REF := WRH_DOC_TYPE_REF, DOC_NUM_GENERATOR_REF := :DOC_NUM_GENERATOR_REF, WRH_DOC_DATE := :WRH_DOC_DATE) WITH AUTONOMOUS TRANSACTION |
| into |
| :NEW_DOC_NUMBER; |
| |
| </code> |
| |
| Пример 2: Показва изпълнението само в случая за изтегляне на номер и изчакването за следващ опит. Този пример е част от горната процедура. |
| |
| При изтегляне на номер на фактура от кочан се извършва ъпдейт и изтегляне на номера в една транзакция. Ако транзакцията продължи около 1 секунда, то през това време, никой друг не може да достъпи същия кочан и да изтегли пореден номер. |
| |
| В този случай при грешка можем да изчакаме определено време (колкото преценим, че е добре) и да опитаме отново. |
| Пример за точно такова изчакване е в следващия пример: |
| |
| <code pascal> |
| repeat_count = 0; |
| NEW_DOC_NUMBER = null; |
| while ((repeat_count < 5) and (NEW_DOC_NUMBER is null)) do |
| begin |
| repeat_count = repeat_count + 1; |
| NEW_DOC_NUMBER = null; |
| update |
| NOM$DOC_NUM_GENERATORS G |
| set |
| G.CURRENT_VALUE = G.CURRENT_VALUE + 1 |
| where |
| G.ID = :DOC_NUM_GENERATOR_REF |
| returning |
| G.CURRENT_VALUE - 1 |
| into |
| :NEW_DOC_NUMBER; |
| when any do |
| begin |
| execute procedure SYS$SLEEP(200); -- ако поискаме повече от 200 мс трябва да поставим съответното време за изчакване тук! |
| NEW_DOC_NUMBER = null; |
| end |
| end |
| if (NEW_DOC_NUMBER is null) then |
| exception CLEAN_TEXT_ERROR ''There was a problem getting an invoice number for the warehouse document!''; |
| |
| </code> |