| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- <?php
- namespace App\Http\Controllers;
- use App\Models\Contractor;
- use App\Models\Product;
- use App\Models\Scopes\YearScope;
- use App\Services\ContractorPriceService;
- use Illuminate\Http\RedirectResponse;
- use Illuminate\Http\Request;
- use Illuminate\View\View;
- use Symfony\Component\HttpFoundation\BinaryFileResponse;
- class ContractorController extends Controller
- {
- protected string $id = 'contractors';
- protected array $header = [
- 'id' => 'ID',
- 'name' => 'Наименование',
- 'legal_name' => 'Юридическое имя',
- 'contract_number' => '№ договора',
- 'contract_date' => 'Дата договора',
- 'organization_form_name' => 'Форма',
- 'tax_rate_name' => 'Налог',
- 'hidden_txt' => 'Скрыт',
- ];
- protected array $searchFields = ['name', 'legal_name', 'contract_number', 'director_name'];
- public function index(Request $request): View
- {
- session(['gp_contractors' => $request->query()]);
- $nav = $this->startNavigationContext($request);
- $allowedSortFields = ['id', 'name', 'legal_name', 'contract_number', 'contract_date', 'organization_form', 'tax_rate', 'hidden'];
- $sortBy = in_array($request->get('sortBy'), $allowedSortFields, true) ? $request->get('sortBy') : 'name';
- $orderBy = $request->get('order') === 'desc' ? 'desc' : 'asc';
- $contractors = Contractor::query();
- if ($request->filled('s')) {
- $search = $request->get('s');
- $contractors->where(function ($query) use ($search) {
- foreach ($this->searchFields as $field) {
- $query->orWhere($field, 'like', '%' . $search . '%');
- }
- });
- }
- $contractors = $contractors->orderBy($sortBy, $orderBy)->get();
- return view('contractors.index', [
- 'active' => 'contractors',
- 'id' => $this->id,
- 'header' => $this->header,
- 'sortBy' => $sortBy,
- 'orderBy' => $orderBy,
- 'searchFields' => $this->searchFields,
- 'contractors' => $contractors,
- 'organizationForms' => Contractor::ORGANIZATION_FORMS,
- 'taxRates' => Contractor::TAX_RATES,
- 'nav' => $nav,
- ]);
- }
- public function create(Request $request, ContractorPriceService $priceService): View
- {
- return $this->showForm($request, null, $priceService);
- }
- public function show(Request $request, Contractor $contractor, ContractorPriceService $priceService): View
- {
- return $this->showForm($request, $contractor, $priceService);
- }
- public function store(Request $request): RedirectResponse
- {
- $validated = $this->validatedContractor($request);
- $contractor = Contractor::query()->create($validated);
- return redirect()->route('contractors.show', $contractor)->with('success', 'Подрядчик создан');
- }
- public function update(Request $request, Contractor $contractor): RedirectResponse
- {
- $contractor->update($this->validatedContractor($request));
- return redirect()->route('contractors.show', $contractor)->with('success', 'Подрядчик сохранён');
- }
- public function updatePrice(Request $request, Contractor $contractor, ContractorPriceService $priceService): RedirectResponse
- {
- $validated = $request->validate([
- 'product_id' => ['required', 'integer', 'exists:products,id'],
- 'name_in_spec' => ['nullable', 'string', 'max:255'],
- 'price' => ['nullable', 'numeric', 'min:0'],
- ]);
- $product = Product::withoutGlobalScope(YearScope::class)->withTrashed()->findOrFail($validated['product_id']);
- $priceService->updatePrice(
- $contractor,
- $product,
- year(),
- $validated['name_in_spec'] ?? null,
- (float) ($validated['price'] ?? 0),
- );
- return redirect()->route('contractors.show', $contractor)->with('success', 'Цена монтажа сохранена');
- }
- public function importPrices(Request $request, Contractor $contractor, ContractorPriceService $priceService): RedirectResponse
- {
- $validated = $request->validate([
- 'import_file' => ['required', 'file', 'mimes:xlsx,xls'],
- ]);
- $result = $priceService->import($contractor, $validated['import_file'], year());
- $message = "Импорт завершён. Обновлено: {$result['updated']}. Без изменений: {$result['unchanged']}. Ошибок: " . count($result['errors']) . '.';
- return redirect()
- ->route('contractors.show', $contractor)
- ->with('success', $message)
- ->with('contractor_import_errors', $result['errors']);
- }
- public function exportPrices(Request $request, Contractor $contractor, ContractorPriceService $priceService): BinaryFileResponse
- {
- $catalogYear = year();
- $path = $priceService->export($contractor, $catalogYear);
- return response()
- ->download($path, 'Цены монтажа ' . $contractor->name . ' ' . $catalogYear . '.xlsx')
- ->deleteFileAfterSend();
- }
- private function showForm(Request $request, ?Contractor $contractor, ContractorPriceService $priceService): View
- {
- $nav = $this->resolveNavToken($request);
- $this->rememberNavigation($request, $nav);
- $year = year();
- return view('contractors.edit', [
- 'active' => 'contractors',
- 'contractor' => $contractor,
- 'organizationForms' => Contractor::ORGANIZATION_FORMS,
- 'taxRates' => Contractor::TAX_RATES,
- 'priceRows' => $contractor ? $priceService->rowsForContractor($contractor, $year) : collect(),
- 'catalogYear' => $year,
- 'nav' => $nav,
- 'back_url' => $this->navigationBackUrl($request, $nav, route('contractors.index', session('gp_contractors'))),
- ]);
- }
- private function validatedContractor(Request $request): array
- {
- return $request->validate([
- 'name' => ['required', 'string', 'max:255'],
- 'legal_name' => ['required', 'string', 'max:255'],
- 'contract_number' => ['required', 'string', 'max:255'],
- 'contract_date' => ['required', 'date'],
- 'director_name' => ['required', 'string', 'max:255'],
- 'organization_form' => ['required', 'string', 'in:' . implode(',', array_keys(Contractor::ORGANIZATION_FORMS))],
- 'tax_rate' => ['required', 'string', 'in:' . implode(',', array_keys(Contractor::TAX_RATES))],
- 'contract_header' => ['required', 'string'],
- 'hidden' => ['nullable', 'boolean'],
- ]) + ['hidden' => false];
- }
- }
|