$data */ public function create(array $data, User $actor): ProductionOrder { return DB::transaction(function () use ($data, $actor): ProductionOrder { $items = Arr::pull($data, 'items', []); unset($data['nav']); $data['source'] = ProductionOrderSource::Manual; $data['contract_shipment_date'] = $this->contractShipmentDate($data); $data['created_by'] = $actor->id; $data['updated_by'] = $actor->id; $order = ProductionOrder::query()->create($data); $this->syncItems($order, $items, $actor); return $order->load(['manager', 'items.catalogItem']); }); } /** @param array $data */ public function update( ProductionOrder $order, array $data, User $actor, bool $syncItems, array $editableItemFields = [], ): ProductionOrder { return DB::transaction(function () use ( $order, $data, $actor, $syncItems, $editableItemFields, ): ProductionOrder { $items = Arr::pull($data, 'items', null); unset($data['nav']); if (array_key_exists('payment_date', $data) || array_key_exists('supply_working_days', $data)) { $data['contract_shipment_date'] = $this->contractShipmentDate([ 'payment_date' => $data['payment_date'] ?? $order->payment_date, 'supply_working_days' => $data['supply_working_days'] ?? $order->supply_working_days, ]); } $data['updated_by'] = $actor->id; $order->update($data); if ($order->wasChanged('status')) { $order->activities()->create([ 'type' => ProductionOrderActivityType::StatusChanged, 'user_id' => $actor->id, 'message' => 'Изменён статус заказа.', ]); } if ($syncItems && is_array($items)) { $this->syncItems($order, $items, $actor); } elseif (is_array($items) && $editableItemFields !== []) { $this->updateItemDetails($order, $items, $editableItemFields); } return $order->refresh()->load(['manager', 'items.catalogItem']); }); } /** * @param array> $items * @param array $editableFields */ private function updateItemDetails(ProductionOrder $order, array $items, array $editableFields): void { foreach ($items as $itemData) { $id = isset($itemData['id']) ? (int) $itemData['id'] : 0; if ($id < 1) { continue; } $order->items()->whereKey($id)->firstOrFail()->update( Arr::only($itemData, $editableFields), ); } } /** * @param array> $items */ private function syncItems(ProductionOrder $order, array $items, User $actor): void { $keptIds = []; foreach (array_values($items) as $sort => $itemData) { $id = isset($itemData['id']) ? (int) $itemData['id'] : null; $payload = Arr::only($itemData, [ 'common_catalog_item_id', 'order_item_number', 'factory_number', 'manufacture_date', ]); $payload['sort'] = $sort; if ($id !== null && $id > 0) { $item = $order->items()->whereKey($id)->firstOrFail(); $item->update($payload); } else { $item = $order->items()->create($payload + ['created_by' => $actor->id]); } $keptIds[] = $item->id; } $order->items()->whereNotIn('id', $keptIds)->delete(); } /** @param array $data */ private function contractShipmentDate(array $data): string { return $this->calendar ->addWorkingDays((string) $data['payment_date'], (int) $data['supply_working_days']) ->toDateString(); } }