$data */ public function create(array $data): StockEntry { $data['unit'] = ($data['entry_type'] ?? '') === 'ingredient' ? 'gram' : 'piece'; $data = $this->resolvePrices($data); return StockEntry::query()->create($data); } /** * @param array $data */ public function update(StockEntry $stockEntry, array $data): StockEntry { if (array_key_exists('entry_type', $data)) { $data['unit'] = ($data['entry_type'] ?? '') === 'ingredient' ? 'gram' : 'piece'; } $data = $this->resolvePrices($data); $stockEntry->update($data); return $stockEntry->fresh(); } /** * Ergänzt Netto-/Brutto-Preis pro kg und den UST-Snapshot. * Es genügt, Netto oder Brutto anzugeben; der jeweils fehlende Wert wird * aus dem gewählten Steuersatz berechnet. * * @param array $data * @return array */ protected function resolvePrices(array $data): array { if (($data['entry_type'] ?? '') !== 'ingredient') { $data['price_per_kg'] = null; $data['price_per_kg_gross'] = null; $data['tax_rate_id'] = null; $data['tax_rate_percent'] = null; return $data; } $percent = null; if (! empty($data['tax_rate_id'])) { $percent = TaxRate::query()->whereKey($data['tax_rate_id'])->value('percent'); } $data['tax_rate_percent'] = $percent; $factor = 1 + ((float) ($percent ?? 0)) / 100; $net = isset($data['price_per_kg']) && $data['price_per_kg'] !== null && $data['price_per_kg'] !== '' ? (float) $data['price_per_kg'] : null; $gross = isset($data['price_per_kg_gross']) && $data['price_per_kg_gross'] !== null && $data['price_per_kg_gross'] !== '' ? (float) $data['price_per_kg_gross'] : null; if ($net !== null && $gross === null) { $gross = round($net * $factor, 4); } elseif ($gross !== null && $net === null) { $net = $factor > 0 ? round($gross / $factor, 4) : $gross; } elseif ($net !== null && $gross !== null) { $gross = round($net * $factor, 4); } $data['price_per_kg'] = $net; $data['price_per_kg_gross'] = $gross; $data['price_total'] = null; return $data; } /** * @param array $data */ public function receive(StockEntry $stockEntry, array $data): StockEntry { $data['status'] = 'received'; $data['received_by'] = auth()->id(); $stockEntry->update($data); return $stockEntry->fresh(); } /** * @return Collection */ public function getByStatus(string $status): Collection { return StockEntry::query() ->where('status', $status) ->orderByDesc('ordered_at') ->get(); } /** * @return Collection */ public function getForIngredient(int $ingredientId): Collection { return StockEntry::query() ->where('ingredient_id', $ingredientId) ->where('status', 'received') ->orderByDesc('received_at') ->get(); } /** * Liste: Pending zuerst (neuestes Bestelldatum), dann Received (neuester Eingang). * * @return Collection */ public function listForIndex(): Collection { $with = [ 'ingredient', 'packagingItem', 'supplier', 'location', 'quality', 'orderedByUser', 'receivedByUser', ]; $pending = StockEntry::query()->with($with)->where('status', 'pending')->orderByDesc('ordered_at')->get(); $received = StockEntry::query()->with($with)->where('status', 'received')->orderByDesc('received_at')->get(); return $pending->concat($received)->values(); } }