refactor(elixir): remove unused qr_code
This commit is contained in:
@@ -1,233 +0,0 @@
|
||||
defmodule ComponentsElixir.QRCode do
|
||||
@moduledoc """
|
||||
QR Code generation and parsing for storage locations.
|
||||
|
||||
Provides functionality to generate QR codes for storage locations
|
||||
and parse them back to retrieve location information.
|
||||
"""
|
||||
|
||||
@doc """
|
||||
Generates a QR code data string for a storage location.
|
||||
|
||||
Format: SL:{level}:{qr_code}:{parent_qr_or_ROOT}
|
||||
|
||||
## Examples
|
||||
|
||||
iex> location = %StorageLocation{level: 1, qr_code: "ABC123", parent: nil}
|
||||
iex> ComponentsElixir.QRCode.generate_qr_data(location)
|
||||
"SL:1:ABC123:ROOT"
|
||||
|
||||
iex> parent = %StorageLocation{qr_code: "SHELF1"}
|
||||
iex> drawer = %StorageLocation{level: 2, qr_code: "DRAW01", parent: parent}
|
||||
iex> ComponentsElixir.QRCode.generate_qr_data(drawer)
|
||||
"SL:2:DRAW01:SHELF1"
|
||||
"""
|
||||
def generate_qr_data(storage_location) do
|
||||
parent_code =
|
||||
case storage_location.parent do
|
||||
nil -> "ROOT"
|
||||
parent -> parent.qr_code
|
||||
end
|
||||
|
||||
"SL:#{storage_location.level}:#{storage_location.qr_code}:#{parent_code}"
|
||||
end
|
||||
|
||||
@doc """
|
||||
Parses a QR code string and extracts components.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> ComponentsElixir.QRCode.parse_qr_data("SL:1:ABC123:ROOT")
|
||||
{:ok, %{level: 1, code: "ABC123", parent: "ROOT"}}
|
||||
|
||||
iex> ComponentsElixir.QRCode.parse_qr_data("invalid")
|
||||
{:error, :invalid_format}
|
||||
"""
|
||||
def parse_qr_data(qr_string) do
|
||||
case String.split(qr_string, ":") do
|
||||
["SL", level_str, code, parent] ->
|
||||
case Integer.parse(level_str) do
|
||||
{level, ""} ->
|
||||
{:ok, %{level: level, code: code, parent: parent}}
|
||||
_ ->
|
||||
{:error, :invalid_level}
|
||||
end
|
||||
_ ->
|
||||
{:error, :invalid_format}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Validates if a string looks like a storage location QR code.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> ComponentsElixir.QRCode.valid_storage_qr?("SL:1:ABC123:ROOT")
|
||||
true
|
||||
|
||||
iex> ComponentsElixir.QRCode.valid_storage_qr?("COMP:12345")
|
||||
false
|
||||
"""
|
||||
def valid_storage_qr?(qr_string) do
|
||||
case parse_qr_data(qr_string) do
|
||||
{:ok, _} -> true
|
||||
_ -> false
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Generates a printable label data structure for a storage location.
|
||||
|
||||
This could be used to generate PDF labels or send to a label printer.
|
||||
"""
|
||||
def generate_label_data(storage_location) do
|
||||
qr_data = generate_qr_data(storage_location)
|
||||
|
||||
%{
|
||||
qr_code: qr_data,
|
||||
name: storage_location.name,
|
||||
path: storage_location.path,
|
||||
level: storage_location.level,
|
||||
description: storage_location.description
|
||||
}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Generates multiple QR codes for disambiguation testing.
|
||||
|
||||
This is useful for testing multi-QR detection scenarios.
|
||||
"""
|
||||
def generate_test_codes(storage_locations) when is_list(storage_locations) do
|
||||
Enum.map(storage_locations, &generate_qr_data/1)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Generates a QR code image (PNG) for a storage location.
|
||||
|
||||
Returns the binary PNG data that can be saved to disk or served directly.
|
||||
|
||||
## Options
|
||||
|
||||
- `:size` - The size of the QR code image in pixels (default: 200)
|
||||
- `:background` - Background color as `{r, g, b}` tuple (default: white)
|
||||
- `:foreground` - Foreground color as `{r, g, b}` tuple (default: black)
|
||||
|
||||
## Examples
|
||||
|
||||
iex> location = %StorageLocation{level: 1, qr_code: "ABC123"}
|
||||
iex> {:ok, png_data} = ComponentsElixir.QRCode.generate_qr_image(location)
|
||||
iex> File.write!("/tmp/qr_code.png", png_data)
|
||||
|
||||
"""
|
||||
def generate_qr_image(storage_location, _opts \\ []) do
|
||||
qr_data = generate_qr_data(storage_location)
|
||||
|
||||
qr_data
|
||||
|> QRCode.create()
|
||||
|> QRCode.render(:png)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Generates and saves a QR code image to the specified file path.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> location = %StorageLocation{level: 1, qr_code: "ABC123"}
|
||||
iex> ComponentsElixir.QRCode.save_qr_image(location, "/tmp/qr_code.png")
|
||||
:ok
|
||||
|
||||
"""
|
||||
def save_qr_image(storage_location, file_path, opts \\ []) do
|
||||
case generate_qr_image(storage_location, opts) do
|
||||
{:ok, png_data} ->
|
||||
# Ensure directory exists
|
||||
file_path
|
||||
|> Path.dirname()
|
||||
|> File.mkdir_p!()
|
||||
|
||||
File.write!(file_path, png_data)
|
||||
:ok
|
||||
|
||||
{:error, reason} ->
|
||||
{:error, reason}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Generates a QR code image URL for serving via Phoenix static files.
|
||||
|
||||
This function generates the QR code image and saves it to the static directory,
|
||||
returning a URL that can be used in templates.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> location = %StorageLocation{id: 123, qr_code: "ABC123"}
|
||||
iex> ComponentsElixir.QRCode.get_qr_image_url(location)
|
||||
"/qr_codes/storage_location_123.png"
|
||||
|
||||
"""
|
||||
def get_qr_image_url(storage_location, opts \\ []) do
|
||||
filename = "storage_location_#{storage_location.id}.png"
|
||||
file_path = Path.join([Application.app_dir(:components_elixir, "priv/static/user_generated/qr_codes"), filename])
|
||||
|
||||
# Generate and save the image if it doesn't exist or if regeneration is forced
|
||||
force_regenerate = Keyword.get(opts, :force_regenerate, false)
|
||||
|
||||
if force_regenerate || !File.exists?(file_path) do
|
||||
case save_qr_image(storage_location, file_path, opts) do
|
||||
:ok -> "/user_generated/qr_codes/#{filename}"
|
||||
{:error, _reason} -> nil
|
||||
end
|
||||
else
|
||||
"/user_generated/qr_codes/#{filename}"
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Generates QR code images for multiple storage locations (bulk generation).
|
||||
|
||||
Returns a list of results indicating success or failure for each location.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> locations = [location1, location2, location3]
|
||||
iex> ComponentsElixir.QRCode.bulk_generate_images(locations)
|
||||
[
|
||||
{:ok, "/qr_codes/storage_location_1.png"},
|
||||
{:ok, "/qr_codes/storage_location_2.png"},
|
||||
{:error, "Failed to generate for location 3"}
|
||||
]
|
||||
|
||||
"""
|
||||
def bulk_generate_images(storage_locations, opts \\ []) do
|
||||
# Use Task.async_stream for concurrent generation with back-pressure
|
||||
storage_locations
|
||||
|> Task.async_stream(
|
||||
fn location ->
|
||||
case get_qr_image_url(location, Keyword.put(opts, :force_regenerate, true)) do
|
||||
nil -> {:error, "Failed to generate QR code for location #{location.id}"}
|
||||
url -> {:ok, url}
|
||||
end
|
||||
end,
|
||||
timeout: :infinity,
|
||||
max_concurrency: System.schedulers_online() * 2
|
||||
)
|
||||
|> Enum.map(fn {:ok, result} -> result end)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Cleans up QR code images for deleted storage locations.
|
||||
|
||||
Should be called when storage locations are deleted to prevent orphaned files.
|
||||
"""
|
||||
def cleanup_qr_image(storage_location_id) do
|
||||
filename = "storage_location_#{storage_location_id}.png"
|
||||
file_path = Path.join([Application.app_dir(:components_elixir, "priv/static/user_generated/qr_codes"), filename])
|
||||
|
||||
if File.exists?(file_path) do
|
||||
File.rm(file_path)
|
||||
else
|
||||
:ok
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user