up
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user