86 lines
3.3 KiB
PHP
86 lines
3.3 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Producto;
|
|
use App\Models\ProductVariant;
|
|
|
|
class EAN13Service
|
|
{
|
|
/**
|
|
* Genera un código de barras EAN-13 único.
|
|
*
|
|
* @param string $countryCode Código de país (2 dígitos)
|
|
* @param int $categoryId ID de la categoría (2 dígitos)
|
|
* @param int $productId ID del producto (5 dígitos)
|
|
* @param int|null $variantId ID de la variante (2 dígitos, opcional)
|
|
* @return string Código de barras EAN-13
|
|
* @throws \Exception Si hay un error en la generación del código
|
|
*/
|
|
public function generateUniqueBarcode($countryCode, $categoryId, $productId, $variantId = null)
|
|
{
|
|
// Formatear los valores con ceros a la izquierda
|
|
$categoryCode = str_pad($categoryId, 2, '0', STR_PAD_LEFT);
|
|
$productCode = str_pad($productId, 5, '0', STR_PAD_LEFT);
|
|
$variantCode = str_pad($variantId ?? 0, 3, '0', STR_PAD_LEFT);
|
|
|
|
// Generar los primeros 12 dígitos del código EAN-13
|
|
$barcodeBase = $countryCode . $categoryCode . $productCode . $variantCode;
|
|
|
|
// Validar que la longitud sea exactamente 12 caracteres
|
|
if (strlen($barcodeBase) !== 12) {
|
|
throw new \Exception("Error: El código base del EAN-13 no tiene 12 caracteres: $barcodeBase");
|
|
}
|
|
|
|
// Intentar generar un código único hasta 5 veces
|
|
$maxAttempts = 5;
|
|
$uniqueBarcode = null;
|
|
|
|
foreach (range(1, $maxAttempts) as $attempt) {
|
|
// Calcular el dígito de control
|
|
$checkDigit = $this->calculateCheckDigit($barcodeBase);
|
|
$barcode = $barcodeBase . $checkDigit;
|
|
|
|
// Verificar si el código de barras ya existe en la base de datos
|
|
$existsInProductVariant = ProductVariant::where('barcode', $barcode)->exists();
|
|
$existsInProducto = Producto::where('codigo_barras', $barcode)->exists();
|
|
|
|
if (!$existsInProductVariant && !$existsInProducto) {
|
|
// Si no existe, asignar el código único y salir del ciclo
|
|
$uniqueBarcode = $barcode;
|
|
break;
|
|
}
|
|
|
|
// Si existe, modificar el código base agregando un sufijo incremental
|
|
$suffix = str_pad($attempt, 3, '0', STR_PAD_LEFT); // Agregar un sufijo de 3 dígitos
|
|
$barcodeBase = substr($barcodeBase, 0, -3) . $suffix; // Reemplazar los últimos 3 dígitos con el sufijo
|
|
}
|
|
|
|
// Retornar el código único si se encontró, o null si no se pudo generar
|
|
return $uniqueBarcode;
|
|
}
|
|
|
|
/**
|
|
* Calcula el dígito de control de un código EAN-13.
|
|
*
|
|
* @param string $barcodeBase Los primeros 12 dígitos del código EAN-13
|
|
* @return int Dígito de control calculado
|
|
* @throws \Exception Si el código base no tiene 12 caracteres
|
|
*/
|
|
private function calculateCheckDigit($barcodeBase)
|
|
{
|
|
if (strlen($barcodeBase) !== 12) {
|
|
throw new \Exception("Error: El código base para el dígito de control no tiene 12 caracteres: $barcodeBase");
|
|
}
|
|
|
|
$sum = 0;
|
|
for ($i = 0; $i < 12; $i++) {
|
|
$digit = (int) $barcodeBase[$i];
|
|
$sum += ($i % 2 === 0) ? $digit : $digit * 3;
|
|
}
|
|
|
|
$remainder = $sum % 10;
|
|
return ($remainder === 0) ? 0 : 10 - $remainder;
|
|
}
|
|
}
|