<?php namespace QUI\ERP; use IntlDateFormatter; use PDO; use QUI; use QUI\ERP\Products\Handler\Fields; use QUI\Utils\Security\Orthos; use function array_filter; use function array_keys; use function array_map; use function array_merge; use function array_unique; use function array_values; use function array_walk; use function count; use function date_create; use function explode; use function implode; use function in_array; use function is_array; use function sort; use function str_replace; use function trim; /** * Class Manufacturers * * Main handler for manufacturer management */ class Manufacturers { /** * Get all group IDs that are assigned to the manufacturer product field * * @return int[] */ public static function getManufacturerGroupIds(): array { $groupIds = []; try { $Conf = QUI::getPackage('quiqqer/erp')->getConfig(); $defaultGroupId = $Conf->get('manufacturers', 'groupId'); if (!empty($defaultGroupId)) { $groupIds[] = (int)$defaultGroupId; } } catch (\Exception $Exception) { QUI\System\Log::writeException($Exception); } if (!QUI::getPackageManager()->isInstalled('quiqqer/products')) { return $groupIds; } // If quiqqer/products is installed also check groups of default product field "Manufacturer" try { $ManufacturerField = Fields::getField(Fields::FIELD_MANUFACTURER); } catch (\Exception $Exception) { QUI\System\Log::writeException($Exception); return $groupIds; } $fieldGroupIds = $ManufacturerField->getOption('groupIds'); if (empty($fieldGroupIds) || !is_array($fieldGroupIds)) { return $groupIds; } array_walk($fieldGroupIds, function (&$groupId) { $groupId = (int)$groupId; }); $groupIds = array_merge($groupIds, $fieldGroupIds); return array_values(array_unique($groupIds)); } /** * Create a new manufacturer user * * @param string $manufacturerId - QUIQQER username * @param array $address * @param array $groupIds - QUIQQER group IDs of manufacturer groups * * @return QUI\Interfaces\Users\User * * @throws Exception * @throws QUI\Exception * @throws QUI\Permissions\Exception */ public static function createManufacturer( string $manufacturerId, array $address = [], array $groupIds = [] ): QUI\Interfaces\Users\User { QUI\Permissions\Permission::checkPermission('quiqqer.erp_manufacturers.create'); $Users = QUI::getUsers(); $manufacturerId = $Users::clearUsername($manufacturerId); // Check ID if ($Users->usernameExists($manufacturerId)) { throw new Exception([ 'quiqqer/erp', 'exception.Manufacturers.createManufacturer.id_already_exists', [ 'userId' => $manufacturerId ] ]); } $SystemUser = $Users->getSystemUser(); $User = $Users->createChild($manufacturerId, $SystemUser); if (!empty($address)) { try { $Address = $User->getStandardAddress(); } catch (QUI\Exception) { $Address = $User->addAddress(); } $needles = [ 'salutation', 'firstname', 'lastname', 'company', 'delivery', 'street_no', 'zip', 'city', 'country' ]; foreach ($needles as $needle) { if (!isset($address[$needle])) { $address[$needle] = ''; } } $Address->setAttribute('salutation', $address['salutation']); $Address->setAttribute('firstname', $address['firstname']); $Address->setAttribute('lastname', $address['lastname']); $Address->setAttribute('company', $address['company']); $Address->setAttribute('delivery', $address['delivery']); $Address->setAttribute('street_no', $address['street_no']); $Address->setAttribute('zip', $address['zip']); $Address->setAttribute('city', $address['city']); $Address->setAttribute('country', $address['country']); // E-Mail if (!empty($address['email']) && Orthos::checkMailSyntax($address['email'])) { $User->setAttribute('email', $address['email']); $Address->addMail($address['email']); } $Address->save(); if (empty($User->getAttribute('firstname'))) { $User->setAttribute('firstname', $address['firstname']); } if (empty($User->getAttribute('lastname'))) { $User->setAttribute('lastname', $address['lastname']); } } // groups $manufacturerGroupIds = self::getManufacturerGroupIds(); foreach ($groupIds as $groupId) { $groupId = (int)$groupId; if (in_array($groupId, $manufacturerGroupIds)) { $User->addToGroup($groupId); } } $User->save($SystemUser); // Set random password and activate $User->setPassword(QUI\Security\Password::generateRandom(), $SystemUser); $User->activate('', $SystemUser); return $User; } /** * Search manufacturers * * @param array $searchParams * @param bool $countOnly (optional) - get count for search result only [default: false] * @return int[]|int - Manufacturer user IDs or count */ public static function search(array $searchParams, bool $countOnly = false): array|int { $Grid = new QUI\Utils\Grid($searchParams); $gridParams = $Grid->parseDBParams($searchParams); $usersTbl = QUI::getDBTableName('users'); $usersAddressTbl = QUI::getDBTableName('users_address'); $binds = []; $where = []; if ($countOnly) { $sql = "SELECT COUNT(*)"; } else { $sql = "SELECT u.`id`, u.`firstname`, u.`lastname`, u.`email`, u.`username`, ua.`company`, u.`usergroup`"; $sql .= ", u.`active`, u.`regdate`"; } $sql .= " FROM `" . $usersTbl . "` as u LEFT JOIN `" . $usersAddressTbl . "` as ua ON u.`address` = ua.`id`"; // Only fetch users in manufacturer groups $gc = 0; $whereOr = []; foreach (self::getManufacturerGroupIds() as $groupId) { $whereOr[] = "u.`usergroup` LIKE :group" . $gc; $bind = 'group' . $gc++; $binds[$bind] = [ 'value' => '%,' . $groupId . ',%', 'type' => PDO::PARAM_STR ]; } if (!empty($whereOr)) { $where[] = "(" . implode(" OR ", $whereOr) . ")"; } // User search $searchFields = [ 'id', 'username', 'email', 'company' ]; if (!empty($searchParams['filter']) && is_array($searchParams['filter'])) { $searchFields = array_filter($searchParams['filter'], function ($value) { return !!(int)$value; }); $searchFields = array_keys($searchFields); // date filters if (!empty($searchParams['filter']['regdate_from'])) { $DateFrom = date_create($searchParams['filter']['regdate_from']); if ($DateFrom) { $DateFrom->setTime(0, 0, 0); $bind = 'datefrom'; $where[] = 'u.`regdate` >= :' . $bind; $binds[$bind] = [ 'value' => $DateFrom->getTimestamp(), 'type' => PDO::PARAM_INT ]; } } if (!empty($searchParams['filter']['regdate_to'])) { $DateTo = date_create($searchParams['filter']['regdate_to']); if ($DateTo) { $DateTo->setTime(23, 59, 59); $bind = 'dateto'; $where[] = 'u.`regdate` <= :' . $bind; $binds[$bind] = [ 'value' => $DateTo->getTimestamp(), 'type' => PDO::PARAM_INT ]; } } } if (!empty($searchParams['search'])) { $searchValue = $searchParams['search']; $fc = 0; $whereOr = []; // search value filters foreach ($searchFields as $filter) { $bind = 'filter' . $fc; switch ($filter) { case 'id': case 'username': case 'firstname': case 'lastname': case 'email': $whereOr[] = 'u.`' . $filter . '` LIKE :' . $bind; break; case 'company': $whereOr[] = 'ua.`' . $filter . '` LIKE :' . $bind; break; default: continue 2; } $binds[$bind] = [ 'value' => '%' . $searchValue . '%', 'type' => PDO::PARAM_STR ]; $fc++; } if (!empty($whereOr)) { $where[] = "(" . implode(" OR ", $whereOr) . ")"; } } // build WHERE query string if (!empty($where)) { $sql .= " WHERE " . implode(" AND ", $where); } // ORDER if (!empty($searchParams['sortOn'])) { $sortOn = Orthos::clear($searchParams['sortOn']); switch ($sortOn) { case 'id': case 'username': case 'firstname': case 'lastname': case 'email': $sortOn = 'u.`' . $sortOn . '`'; break; case 'company': $sortOn = 'ua.`' . $sortOn . '`'; break; } $order = "ORDER BY " . $sortOn; if (!empty($searchParams['sortBy'])) { $order .= " " . Orthos::clear($searchParams['sortBy']); } else { $order .= " ASC"; } $sql .= " " . $order; } // LIMIT if (!empty($gridParams['limit']) && !$countOnly) { $sql .= " LIMIT " . $gridParams['limit']; } else { if (!$countOnly) { $sql .= " LIMIT " . 20; } } $Stmt = QUI::getPDO()->prepare($sql); // bind search values foreach ($binds as $var => $bind) { $Stmt->bindValue(':' . $var, $bind['value'], $bind['type']); } try { $Stmt->execute(); $result = $Stmt->fetchAll(PDO::FETCH_ASSOC); } catch (\Exception $Exception) { QUI\System\Log::writeException($Exception); return []; } if ($countOnly) { return (int)current(current($result)); } return $result; } /** * Parse data and prepare for frontend use with GRID * * @param array $data - Search result IDs * @return array */ public static function parseListForGrid(array $data): array { $localeCode = QUI::getLocale()->getLocalesByLang( QUI::getLocale()->getCurrent() ); $DateFormatter = new IntlDateFormatter( $localeCode[0], IntlDateFormatter::SHORT, IntlDateFormatter::NONE ); $DateFormatterLong = new IntlDateFormatter( $localeCode[0], IntlDateFormatter::SHORT, IntlDateFormatter::SHORT ); $result = []; $Groups = QUI::getGroups(); $Users = QUI::getUsers(); foreach ($data as $entry) { $entry['usergroup'] = trim($entry['usergroup'], ','); $entry['usergroup'] = explode(',', $entry['usergroup']); $entry['usergroup'] = array_map(function ($groupId) { return (int)$groupId; }, $entry['usergroup']); $groups = array_map(function ($groupId) use ($Groups) { try { $Group = $Groups->get($groupId); return $Group->getName(); } catch (QUI\Exception) { } return ''; }, $entry['usergroup']); sort($groups); $groups = implode(', ', $groups); $groups = str_replace(',,', '', $groups); $groups = trim($groups, ','); $addressData = []; $Address = null; try { $User = $Users->get($entry['id']); $Address = $User->getStandardAddress(); } catch (QUI\Exception) { } if ($Address && (empty($entry['firstname']) || empty($entry['lastname']))) { $name = []; if ($Address->getAttribute('firstname')) { $entry['firstname'] = $Address->getAttribute('firstname'); $name[] = $Address->getAttribute('firstname'); } if ($Address->getAttribute('lastname')) { $entry['lastname'] = $Address->getAttribute('lastname'); $name[] = $Address->getAttribute('lastname'); } if (!empty($name)) { $addressData[] = implode(' ', $name); } } if ($Address) { $addressData[] = $Address->getText(); if (empty($entry['email'])) { $mails = $Address->getMailList(); if (count($mails)) { $entry['email'] = $mails[0]; } } if (empty($entry['company'])) { $entry['company'] = $Address->getAttribute('company'); } } $result[] = [ 'id' => (int)$entry['id'], 'status' => !!$entry['active'], 'username' => $entry['username'], 'firstname' => $entry['firstname'], 'lastname' => $entry['lastname'], 'company' => $entry['company'], 'email' => $entry['email'], 'regdate' => $DateFormatterLong->format($entry['regdate']), 'usergroup_display' => $groups, 'usergroup' => $entry['usergroup'], 'address_display' => implode(' - ', $addressData) ]; } return $result; } }