Друзья, добрый день!
Подскажите как организовать такой функционал: если накладная проведена, нельзя менять клиента.
мой вариант сделать собственный валидатор в модели, но может есть другие методы?
и связанный вопрос: где организовать логику типа: при проведении накладной сделать то-то. А ля БД триггер уровня строки. То есть если старый атрибут $model->ok пуст а новый нет. Есть мысль закинуть все в afterSave но так ли по канонам?
Заранее спасибо за науку!
Валидация. Зависимые атрибуты
Re: Валидация. Зависимые атрибуты
По канонам – делать для каждой операции отдельные экшены со своими формами. В данном случае вынести операции проведения накладной и смены клиента. И там уже по месту что-то делать или проверять.
Re: Валидация. Зависимые атрибуты
А по месту этот как раз где именно? Я вот пытаюсь валидацдию осилить но никак не пойму почему у меня errors всегда пусто и валидация проходит:
Я из КРУДА работаю с формой приходной накладной, там все атрибуты в куче, а надо для каждого атрибута отдельную форму? Не могу проникнуться идеей...
Код: Выделить всё
$model = new ZmPrh();
if ($model->load(Yii::$app->request->post()) ) {
$model->validate();
$model->addError('user_ins', 'wtf?');
Yii::warning(var_dump($model->errors));
$model->save();
}
Re: Валидация. Зависимые атрибуты
В КРУДЕ обычно либо сразу сохраняют с валидацией:
Код: Выделить всё
if ($model->load(Yii::$app->request->post() && $model->save()) ) {
return $this->refresh();
}
Код: Выделить всё
if ($model->load(Yii::$app->request->post() && $model->validate()) ) {
...
$model->save(false);
return $this->refresh();
}
Re: Валидация. Зависимые атрибуты
Ну не все же там поля равноправные.
Есть поля, которые можно редактировать в любое время. Их можно оставить в actionUpdate.
А есть более сложные бизнес-операции вроде смены контрагента и проведения накладной. Их можно сделать отдельными кнопками и экшенами вроде actionChangeCounterparty и actionCarryOut. И как раз там всё проверять и проводить.
Для проверок и проводок можно в накладную добавить методы с понятными названиями:
Код: Выделить всё
class ZmPrh extends ActiveRecord
{
// ...
public function carryOut(): void
{
if ($this->isCarriedOut()) {
throw new DomainException('Накладная уже проведена.');
}
$this->ok = true;
}
public function isCarriedOut(): bool
{
return $this->ok;
}
public function changeCounterparty(int $ins): void
{
if (!$this->canChangeCounterparty()) {
throw new DomainException('Нельзя менять контрагента проведённой накладной.');
}
if ($ins === $this->user_ins) {
throw new DomainException('Этот контрагент уже назначен.');
}
$this->user_ins = $ins;
}
public function canChangeCounterparty(): bool
{
return !$this->ok;
}
}
Код: Выделить всё
public function actionCarryOut(int $id, Session $session): Response
{
$model = $this->loadModel($id);
try {
$model->carryOut();
$model->save(false);
$session->setFlash('success', 'Накладная проведена.');
} catch (DomainException $e) {
$session->setFlash('error', $e->getMessage());
}
return $this->back();
}
public function actionChangeCounterparty(int $id, Request $request, Session $session, Mailer $mailer): Response|string
{
$model = $this->loadModel($id);
$form = new ChangeCounterpartyForm(['ins' => $model->user_ins]);
if ($form->load($request->post()) && $form->validate()) {
try {
$model->changeCounterparty($form->ins);
$model->save(false);
$mailer->compose('mail', ['model' => $model])->setTo('...')->setSubject('...')->send();
$session->setFlash('success', 'Контрагент изменён.');
return $this->redirect(['view', 'id' => $id]);
} catch (DomainException $e) {
$session->setFlash('error', $e->getMessage());
}
}
return $this->render('change-counterparty', ['model' => $model, 'form' => $form]);
}
Код: Выделить всё
<p>
<?= Html::a('Изменить', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']) ?>
<?php if (!$model->isCarriedOut()): ?>
<?= Html::a('Провести', ['carry-out', 'id' => $model->id], ['class' => 'btn btn-success', 'data' => [
'method' => 'post', 'confirm' => 'Провести?'
]]) ?>
<?php endif; ?>
<?php if ($model->canChangeCounterparty()): ?>
<?= Html::a('Сменить контрагента', ['change-counterparty', 'id' => $model->id], ['class' => 'btn btn-primary']) ?>
<?php endif; ?>
<?= Html::a('Удалить', ['delete', 'id' => $model->id], ['class' => 'btn btn-danger', 'data' => [
'method' => 'post', 'confirm' => 'Удалить?'
]]) ?>
</p>
Re: Валидация. Зависимые атрибуты
Дмитрий, благодарю!
Отдельный респект за твои ценные обучающие материалы!
Отдельный респект за твои ценные обучающие материалы!
