Commit 8353e628 authored by DevPilot's avatar DevPilot

feat(procurement): allow re-tendering after the 3-offer gate rejects a tender

When fewer than three offers pass technical evaluation the tender is
flagged "تحتاج إعادة طرح" — but that status also hid the invite-vendors
form, so there was no way to actually invite more vendors and the
process dead-ended with no route forward.

Adds a "إعادة طرح المناقصة" action next to the rejection reason that
returns the tender to published and clears the reason, so additional
vendors can be invited and their offers recorded.
parent 831a3e96
......@@ -159,6 +159,35 @@ class TenderController extends Controller
return $this->redirect('/procurement/tenders/' . $id)->withSuccess('تجاوزت العملية الحد الأدنى (' . $result['accepted_count'] . ' عروض مقبولة فنيًا) — انتقلت للجنة المالية');
}
/**
* إعادة طرح المناقصة بعد ما البوابة رفضتها لقلة العروض المقبولة فنيًا.
*
* من غير الإجراء ده المناقصة بتفضل واقفة عند «تحتاج إعادة طرح» من غير أي
* طريقة تدعو بيها موردين جدد — والدورة بتقف.
*/
public function reopen(Request $request, string $id): Response
{
$this->authorize('procurement.tender.manage');
$db = App::getInstance()->db();
$tender = $db->selectOne("SELECT * FROM procurement_tenders WHERE id = ?", [(int) $id]);
if (!$tender) {
return $this->redirect('/procurement/tenders')->withError('كراسة الشروط غير موجودة');
}
if ($tender['status'] !== 'needs_retender') {
return $this->redirect('/procurement/tenders/' . $id)->withError('إعادة الطرح متاحة فقط للمناقصات التي تحتاج إعادة طرح');
}
$db->update('procurement_tenders', [
'status' => 'published',
'retender_reason' => null,
'updated_at' => date('Y-m-d H:i:s'),
], 'id = ?', [(int) $id]);
return $this->redirect('/procurement/tenders/' . $id)
->withSuccess('تمت إعادة طرح المناقصة — تقدر دلوقتي تدعو موردين إضافيين وتسجّل عروضهم');
}
public function award(Request $request, string $id): Response
{
$this->authorize('procurement.tender.manage');
......
......@@ -26,6 +26,7 @@ return [
['POST', '/procurement/tenders/{id}/invite-vendors', 'Procurement\Controllers\TenderController@inviteVendors', ['auth', 'csrf'], 'procurement.tender.manage'],
['POST', '/procurement/tenders/{id}/quotes/{quoteId}/technical-evaluate', 'Procurement\Controllers\TenderController@technicalEvaluate', ['auth', 'csrf'], 'procurement.tender.manage'],
['POST', '/procurement/tenders/{id}/check-gate', 'Procurement\Controllers\TenderController@checkGate', ['auth', 'csrf'], 'procurement.tender.manage'],
['POST', '/procurement/tenders/{id}/reopen', 'Procurement\Controllers\TenderController@reopen', ['auth', 'csrf'], 'procurement.tender.manage'],
['POST', '/procurement/tenders/{id}/award', 'Procurement\Controllers\TenderController@award', ['auth', 'csrf'], 'procurement.tender.manage'],
['POST', '/procurement/tenders/{id}/convert-to-pos', 'Procurement\Controllers\TenderController@convertToPos', ['auth', 'csrf'], 'procurement.pr.convert'],
......
......@@ -41,6 +41,13 @@ $technicalColors = ['pending' => '#6B7280', 'accepted' => '#059669', 'rejected'
<?php if ($tender['status'] === 'needs_retender'): ?>
<div style="margin-top:12px;padding:12px;background:#FEE2E2;border-radius:6px;font-size:13px;color:#991B1B;font-weight:600;">
<?= e($tender['retender_reason']) ?>
<?php if (can('procurement.tender.manage')): ?>
<form method="POST" action="/procurement/tenders/<?= (int) $tender['id'] ?>/reopen" style="margin-top:10px;">
<?= csrf_field() ?>
<button type="submit" class="btn btn-sm" style="background:#991B1B;color:#fff;border:none;"
onclick="return confirm('إعادة طرح المناقصة لدعوة موردين إضافيين؟');">إعادة طرح المناقصة</button>
</form>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment