diff --git a/Controller/NewServicioAT.php b/Controller/NewServicioAT.php index d18bc18..5883019 100644 --- a/Controller/NewServicioAT.php +++ b/Controller/NewServicioAT.php @@ -29,6 +29,7 @@ use FacturaScripts\Dinamic\Model\MaquinaAT; use FacturaScripts\Dinamic\Model\RoleAccess; use FacturaScripts\Dinamic\Model\ServicioAT; +use Throwable; /** * Description of NewServicioAT @@ -123,10 +124,6 @@ public function privateCore(&$response, $user, $permissions) } switch ($action) { - case 'checkDuplicateCustomer': - $data = $this->checkDuplicateCustomerAction(); - break; - case 'findCustomer': $data = $this->findCustomerAction(); break; @@ -164,34 +161,6 @@ public function privateCore(&$response, $user, $permissions) } } - protected function checkDuplicateCustomerAction(): array - { - $wheres = []; - $name = $this->request->get('name', ''); - $cifnif = $this->request->get('cifnif', ''); - - if (false === empty($name)) { - $wheres[] = 'LOWER(nombre) = ' . $this->dataBase->var2str(strtolower($name)); - $wheres[] = 'LOWER(razonsocial) = ' . $this->dataBase->var2str(strtolower($name)); - } - - if (false === empty($cifnif)) { - $wheres[] = 'LOWER(cifnif) = ' . $this->dataBase->var2str(strtolower($cifnif)); - } - - if (empty($wheres)) { - return ['checkDuplicateCustomer' => false]; - } - - $sql = 'SELECT codcliente' - . ' FROM clientes' - . ' WHERE ' . implode(' OR ', $wheres); - - return count($this->dataBase->select($sql)) > 0 - ? ['checkDuplicateCustomer' => true] - : ['checkDuplicateCustomer' => false]; - } - protected function checkMachine(): bool { if (empty($this->idmaquina)) { @@ -311,10 +280,33 @@ protected function saveNewCustomerAction(): array return ['saveNewCustomer' => false]; } + $name = trim($this->request->get('name', '')); + if ($name === '') { + Tools::log()->warning('invalid-request'); + return ['saveNewCustomer' => false]; + } + + // si el cifnif ya existe en otro cliente avisamos, pero permitimos crearlo igualmente + $cifnif = trim($this->request->get('cifnif', '')); + $confirmed = $this->request->get('cifnif_confirmed', '0') === '1'; + if ($cifnif !== '' && false === $confirmed) { + $duplicated = $this->findCustomersByCifnif($cifnif); + if (false === empty($duplicated)) { + return [ + 'saveNewCustomer' => false, + 'duplicatedCifnif' => true, + 'duplicatedCifnifMessage' => Tools::trans('duplicated-cifnif-customer', [ + '%cifnif%' => $cifnif, + '%customers%' => implode(', ', $duplicated) + ]), + ]; + } + } + // creamos el cliente $customer = new Cliente(); - $customer->nombre = $this->request->get('name'); - $customer->cifnif = $this->request->get('cifnif', ''); + $customer->nombre = $name; + $customer->cifnif = $cifnif; $customer->email = $this->request->get('email'); $customer->telefono1 = $this->request->get('phone1'); $customer->telefono2 = $this->request->get('phone2'); @@ -324,20 +316,34 @@ protected function saveNewCustomerAction(): array $customer = $resultExtension; } - if (false === $customer->save()) { - Tools::log()->error('save-error'); - return ['saveNewCustomer' => false]; - } + $this->dataBase->beginTransaction(); + try { + if (false === $customer->save()) { + $this->dataBase->rollback(); + Tools::log()->error('save-error'); + return ['saveNewCustomer' => false]; + } - // modificamos la dirección - foreach ($customer->getAddresses() as $address) { - $address->direccion = $this->request->get('address'); - $address->codpostal = $this->request->get('zip'); - $address->ciudad = $this->request->get('city'); - $address->provincia = $this->request->get('province'); - $address->codpais = $this->request->get('country'); - $address->save(); - break; + // modificamos la dirección + foreach ($customer->getAddresses() as $address) { + $address->direccion = $this->request->get('address'); + $address->codpostal = $this->request->get('zip'); + $address->ciudad = $this->request->get('city'); + $address->provincia = $this->request->get('province'); + $address->codpais = $this->request->get('country'); + if (false === $address->save()) { + $this->dataBase->rollback(); + Tools::log()->error('save-error'); + return ['saveNewCustomer' => false]; + } + break; + } + + $this->dataBase->commit(); + } catch (Throwable $e) { + $this->dataBase->rollback(); + Tools::log()->error($e->getMessage()); + return ['saveNewCustomer' => false]; } return [ @@ -346,6 +352,18 @@ protected function saveNewCustomerAction(): array ]; } + /** Devuelve los clientes que ya tienen este cifnif, como 'código - nombre'. */ + private function findCustomersByCifnif(string $cifnif): array + { + $names = []; + $where = [Where::eq('cifnif', $cifnif)]; + foreach (Cliente::all($where, ['LOWER(nombre)' => 'ASC'], 0, 5) as $customer) { + $names[] = $customer->codcliente . ' - ' . $customer->nombre; + } + + return $names; + } + protected function saveNewMachineAction(): array { if (false === $this->user->can('EditMaquinaAT', 'update')) { diff --git a/Test/main/NewServicioAtTest.php b/Test/main/NewServicioAtTest.php new file mode 100644 index 0000000..4c7f337 --- /dev/null +++ b/Test/main/NewServicioAtTest.php @@ -0,0 +1,173 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +namespace FacturaScripts\Test\Plugins; + +use FacturaScripts\Core\Base\ControllerPermissions; +use FacturaScripts\Core\Request; +use FacturaScripts\Core\Response; +use FacturaScripts\Dinamic\Model\Cliente; +use FacturaScripts\Dinamic\Model\Page; +use FacturaScripts\Dinamic\Model\User; +use FacturaScripts\Plugins\Servicios\Controller\NewServicioAT; +use FacturaScripts\Test\Traits\DefaultSettingsTrait; +use FacturaScripts\Test\Traits\LogErrorsTrait; +use FacturaScripts\Test\Traits\RandomDataTrait; +use PHPUnit\Framework\TestCase; + +final class NewServicioAtTest extends TestCase +{ + use DefaultSettingsTrait; + use LogErrorsTrait; + use RandomDataTrait; + + public static function setUpBeforeClass(): void + { + self::setDefaultSettings(); + + // la página NewServicioAT se registra normalmente al desplegar el plugin; + // la creamos aquí si el entorno de test no la tiene ya instalada + $page = new Page(); + if (false === $page->load('NewServicioAT')) { + $page->name = 'NewServicioAT'; + $page->title = 'NewServicioAT'; + $page->menu = 'sales'; + $page->showonmenu = false; + $page->save(); + } + } + + public function testSaveNewCustomerCreatesCustomer(): void + { + $user = $this->getRandomUser(); + $user->admin = true; + $this->assertTrue($user->save()); + + $codcliente = null; + try { + $data = $this->saveNewCustomer($user, [ + 'name' => 'Cliente nuevo test', + 'cifnif' => '', + 'address' => 'Calle Test 1', + ]); + + $this->assertTrue($data['saveNewCustomer'] ?? false); + $this->assertArrayNotHasKey('duplicatedCifnif', $data); + + $codcliente = $data['codcliente']; + $customer = new Cliente(); + $this->assertTrue($customer->load($codcliente)); + $this->assertEquals('Cliente nuevo test', $customer->nombre); + } finally { + if ($codcliente !== null) { + $customer = new Cliente(); + if ($customer->load($codcliente)) { + $this->assertTrue($customer->delete()); + } + } + $this->assertTrue($user->delete()); + } + } + + public function testSaveNewCustomerRejectsEmptyName(): void + { + $user = $this->getRandomUser(); + $user->admin = true; + $this->assertTrue($user->save()); + + try { + $data = $this->saveNewCustomer($user, [ + 'name' => ' ', + 'cifnif' => '', + ]); + + $this->assertFalse($data['saveNewCustomer'] ?? true); + $this->assertArrayNotHasKey('codcliente', $data); + } finally { + $this->assertTrue($user->delete()); + } + } + + public function testSaveNewCustomerDetectsDuplicatedCifnif(): void + { + $user = $this->getRandomUser(); + $user->admin = true; + $this->assertTrue($user->save()); + + $existing = $this->getRandomCustomer(); + $existing->cifnif = 'B' . mt_rand(1, 999999); + $this->assertTrue($existing->save()); + + try { + // sin confirmar, con un cifnif ya usado, no debe crear el cliente + $data = $this->saveNewCustomer($user, [ + 'name' => 'Cliente duplicado test', + 'cifnif' => $existing->cifnif, + 'cifnif_confirmed' => '0', + ]); + + $this->assertFalse($data['saveNewCustomer'] ?? true); + $this->assertTrue($data['duplicatedCifnif'] ?? false); + $this->assertStringContainsString($existing->cifnif, $data['duplicatedCifnifMessage']); + + // confirmando, sí debe crear el cliente aunque el cifnif esté duplicado + $data = $this->saveNewCustomer($user, [ + 'name' => 'Cliente duplicado test', + 'cifnif' => $existing->cifnif, + 'cifnif_confirmed' => '1', + ]); + + $this->assertTrue($data['saveNewCustomer'] ?? false); + $this->assertArrayNotHasKey('duplicatedCifnif', $data); + + $newCustomer = new Cliente(); + $this->assertTrue($newCustomer->load($data['codcliente'])); + $this->assertEquals($existing->cifnif, $newCustomer->cifnif); + + $this->assertTrue($newCustomer->delete()); + } finally { + $this->assertTrue($existing->delete()); + $this->assertTrue($user->delete()); + } + } + + protected function tearDown(): void + { + $this->logErrors(); + } + + private function saveNewCustomer(User $user, array $request): array + { + $controller = new NewServicioAT('NewServicioAT', '/NewServicioAT'); + $controller->request = new Request([ + 'request' => array_merge([ + 'action' => 'saveNewCustomer', + 'ajax' => true, + ], $request), + ]); + + $permissions = new ControllerPermissions(); + $permissions->set(true, 99, true, true); + + $response = new Response(); + $controller->privateCore($response, $user, $permissions); + + return json_decode($response->getContent(), true) ?? []; + } +} diff --git a/View/NewServicioAT.html.twig b/View/NewServicioAT.html.twig index ddea456..39dad97 100644 --- a/View/NewServicioAT.html.twig +++ b/View/NewServicioAT.html.twig @@ -131,21 +131,17 @@
{{ trans('name') }} - +
{{ trans('cifnif') }} + oninput="document.getElementById('newCustomerCifnifConfirmed').value = '0'"/> +
-
- {{ trans('duplicate-customer-name-or-cif') }} -
@@ -347,26 +343,10 @@ {{ parent() }}