'good', 'reject_stock' => 'reject', 'retail_stock' => 'retail', ]; public function paginated(Model $model, int $perPage = 20): LengthAwarePaginator { return StockMutation::query() ->where('stockable_type', get_class($model)) ->where('stockable_id', $model->id) ->with('user:id,username,email') ->latest() ->paginate($perPage); } public function recordInitial(Model $model, array $stockData, string $description = 'Stok awal'): void { $userId = auth()->id(); foreach (self::QUALITY_MAP as $field => $quality) { $quantity = (int) ($stockData[$field] ?? 0); if ($quantity > 0) { StockMutation::create([ 'user_id' => $userId, 'stockable_type' => get_class($model), 'stockable_id' => $model->id, 'type' => 'in', 'quantity' => $quantity, 'stock_before' => 0, 'stock_after' => $quantity, 'stock_quality' => $quality, 'description' => $description, ]); } } } public function recordAdjustment(Model $model, array $oldData, array $newData, string $description = 'Penyesuaian stok'): void { $userId = auth()->id(); foreach (self::QUALITY_MAP as $field => $quality) { $old = (int) ($oldData[$field] ?? 0); $new = (int) ($newData[$field] ?? 0); $diff = $new - $old; if ($diff !== 0) { StockMutation::create([ 'user_id' => $userId, 'stockable_type' => get_class($model), 'stockable_id' => $model->id, 'type' => $diff > 0 ? 'in' : 'out', 'quantity' => $diff, 'stock_before' => $old, 'stock_after' => $new, 'stock_quality' => $quality, 'description' => $description, ]); } } } public function recordBulkInitial(Collection $variants, array $stockDataMap, string $description = 'Stok awal'): void { $userId = auth()->id(); $now = now(); $mutations = []; foreach ($variants as $variant) { $stockData = $stockDataMap[$variant->id] ?? []; foreach (self::QUALITY_MAP as $field => $quality) { $quantity = (int) ($stockData[$field] ?? 0); if ($quantity > 0) { $mutations[] = [ 'user_id' => $userId, 'stockable_type' => ProductVariant::class, 'stockable_id' => $variant->id, 'type' => 'in', 'quantity' => $quantity, 'stock_before' => 0, 'stock_after' => $quantity, 'stock_quality' => $quality, 'description' => $description, 'created_at' => $now, 'updated_at' => $now, ]; } } } if ($mutations !== []) { DB::table('stock_mutations')->insert($mutations); } } public function recordBulkAdjustment(Collection $variants, array $oldDataMap, array $newDataMap, string $description = 'Penyesuaian stok'): void { $userId = auth()->id(); $now = now(); $mutations = []; foreach ($variants as $variant) { $oldData = $oldDataMap[$variant->id] ?? []; $newData = $newDataMap[$variant->id] ?? []; foreach (self::QUALITY_MAP as $field => $quality) { $old = (int) ($oldData[$field] ?? 0); $new = (int) ($newData[$field] ?? 0); $diff = $new - $old; if ($diff !== 0) { $mutations[] = [ 'user_id' => $userId, 'stockable_type' => ProductVariant::class, 'stockable_id' => $variant->id, 'type' => $diff > 0 ? 'in' : 'out', 'quantity' => $diff, 'stock_before' => $old, 'stock_after' => $new, 'stock_quality' => $quality, 'description' => $description, 'created_at' => $now, 'updated_at' => $now, ]; } } } if ($mutations !== []) { DB::table('stock_mutations')->insert($mutations); } } public function recordTransfer( Model $model, int $quantity, string $fromQuality, string $toQuality, int $fromBefore, int $toBefore, string $description = 'Transfer stok', ): void { DB::transaction(function () use ($model, $quantity, $fromQuality, $toQuality, $fromBefore, $toBefore, $description) { $userId = auth()->id(); StockMutation::create([ 'user_id' => $userId, 'stockable_type' => get_class($model), 'stockable_id' => $model->id, 'type' => 'out', 'quantity' => -$quantity, 'stock_before' => $fromBefore, 'stock_after' => $fromBefore - $quantity, 'stock_quality' => $fromQuality, 'description' => $description, ]); StockMutation::create([ 'user_id' => $userId, 'stockable_type' => get_class($model), 'stockable_id' => $model->id, 'type' => 'in', 'quantity' => $quantity, 'stock_before' => $toBefore, 'stock_after' => $toBefore + $quantity, 'stock_quality' => $toQuality, 'description' => $description, ]); }); } }