На главную   На главную   Форумы Новости Документация Скачать Купить  
Регистрация  
Система Allegro
Oб Allegro Характеристики Пример конфигурации Документация База ошибок Развитие
Версия для печати К списку книг Вернуться к оглавлению Предыдущий параграф Следующий параграф
Поиск по книге

Глава 9. СОЗДАЕМ ОКОННЫЙ ИНТЕРФЕЙС ДОКУМЕНТА «ПРОДАЖА»

Реализуем проверку текущего количества товара на складе в документе «Продажа».

При сохранении документа «Продажа», если установлена птичка « Товар отгружен», нужно проверить наличие товара на складе, чтобы убедиться, что не отгружается больше единиц товара, чем это возможно физически. Для этого после первого проведения документа, непосредственно перед расчетом средней стоимости вставим проверку результирующего количества товара на складе. И если это количество стало отрицательным, прервем выполнение команды сохранения, не дойдя до подтверждения транзакции.

Добавим еще один компонент IBQuery на форму SaleForm.

Придадим в Инспекторе объектов его свойствам значения:


Свойство Значение
Transaction traCurrent
DataSource dsrMaster
Name qryTestQuantity

Дважды щелкнув на свойстве SQL, вызовем редактор SQL- запросов и впишем в него текст:

select
  a.object_id,
  o.short_name name,
  sum(a.quantity_debit - a.quantity_credit) quantity
from
  acc_turn a, object_names o
where
  a.acc_id = :stock_acc and
  a.op_date <= :entry_date and
  a.object_id in (select goods from sale_item where id = :id) and
  a.object_id = o.object_id
group by
  a.object_id,
  o.short_name
having
  sum(a.quantity_debit - a.quantity_credit) < 0

Обратим внимание, что запрос параметризованный. Параметры stock_ acc, entry_date и id перед открытием запроса компонент qryTestQuantity получит из соответствующих полей компонента qryMaster, благодаря тому, что свойству DataSource компонента qryTestQuantity назначен источник dsrMaster .

Осталось добавить активизацию этого запроса и проверку результата в обработчик команды actSave. Добавим объявление новой функции в секцию private класса формы (показано жирным шрифтом):

private
    { Private declarations }
    procedure UpdatePrice(PriceQuery: TDataSet);
    function Save: boolean;
  public
    { Public declarations }
  end;

Добавим реализацию этой функции в раздел implementation модуля:

procedure TSaleForm.Save: boolean;
begin
end;

Вырежем весь текст из обработчика actSave, вставим его в тело функции и добавим ряд операторов (добавленные операторы выделены жирным шрифтом):

procedure TSaleForm.Save: boolean;
begin
  Result := False;
  qryTotals.Open;
  qryMaster.Edit;
  qryMaster.FieldByName('TOTAL_L').AsCurrency := qryTotals.Fields[0].AsCurrency;
  qryMaster.FieldByName('TOTAL_R').AsCurrency := qryTotals.Fields[1].AsCurrency;
  qryMaster.FieldByName('TOTAL_S').AsCurrency := qryTotals.Fields[2].AsCurrency;
  qryMaster.Post;
  qryTotals.Close;
  MakeEntries('SALE', qryMaster.FieldByName('ID').AsInteger, traCurrent);
  if qryMaster.FieldByName('HAS_ENTRY').AsInteger = 1 then
  begin
    with qryTestQuantity do
    begin
      Open; //открываем запрос количеств
      if not qryTestQuantity.IsEmpty then //если результирующий набор не пуст
      begin
        {находим позицию в документе}
        qryDetail.Locate('GOODS', FieldByName('OBJECT_ID').AsInteger, MkSet());
        dbgDetail.SelectedField := qryDetail.FieldByName('QUANTITY');
        {выдаем сообщение}
        MessageDlg('Недостаточно товара на складе:'#13+
          FieldByName('NAME').AsString, mtError, MkSet(mbOK), 0);
        Close; //закрываем запрос количеств
        exit; //выходим из процедуры сохранения
      end
      else
        Close; //закрываем запрос количеств
    end;
    {Вызываем перерасчет себестоимости}
    qrySetItemCost.ExecSQL;
    {повторно проводим документ}
    MakeEntries('SALE', qryMaster.FieldByName('ID').AsInteger, traCurrent);
  end;
  traCurrent.CommitRetaining; //подтвердить транзакцию
  Modified := False;
  actSave.Enabled := Modified;
  RefreshExplorer; //пересветить "Проводник по документам"
  RefreshBalance;  //пересветить "Баланс"
  Result := True;
end;

Обратим внимание, что вначале мы присваиваем результату, который должна вернуть эта функция, значение False, а в самом конце – присваиваем True. Поэтому функция вернет True только в том случае, если функция сохранения довела свою работу до конца. Если количество какого-то товара на складе, входящего в данный документ, стало отрицательным – вызовется команда exit, которая прервет выполнение функции и та вернет значение False.

В обработчик actSave вместо прежнего текста теперь вставим вызов этой функции:

procedure TSaleForm.actSaveExecute(Sender: TObject);
begin
  Save;
end;

Изменим также обработчик события формы OnCloseQuery: заменим строку

  mrYes:  actSaveExecute(nil); //вызов обработчика OnExecute команды actSave

на вызов функции Save:

procedure TSaleForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  if Modified then
  case MessageDlg(
      'Сохранить изменения в документе ?', mtConfirmation,
      mkSet(mbYes, mbNo, mbCancel), 0) of
  mrYes:  CanClose := Save; //вызов функции Save
  mrCancel: Canclose := False;
  end;
end;

При попытке закрыть окно, если документ редактировался, возникает предложение сохранить изменения. Если пользователь ответил «Да», но при сохранении выяснилось, что товара на складе недостаточно , то сохранение не произойдет и окно не закроется, так как переменной CanClose в обработчике OnCloseQuery присвоится значение False .

Установим в переменных контекста какой-нибудь документ продаж. Запустим проект и попробуем значительно увеличить количество отгружаемого товара. При попытке сохранить изменения мы получим сообщение «Недостаточно товара на складе» и документ не будет сохранен:



Выйдем из режима дизайнера и создадим архивную копию базы ( меню Инструменты/Архивация базы).

Итак, мы полностью закончили интерфейс ввода документа «Продажа ». Нам осталось лишь реализовать печать счетов-фактур и накладных.



Пример создания склада в Allegro Наверх