|
|
@@ -2,14 +2,27 @@
|
|
|
|
|
|
namespace App\Service\Dolibarr\DolibarrSync;
|
|
|
|
|
|
+use App\Entity\Access\Access;
|
|
|
use App\Entity\Core\AddressPostal;
|
|
|
-use App\Entity\Organization\OrganizationAddressPostal;
|
|
|
+use App\Entity\Organization\Organization;
|
|
|
+use App\Enum\Access\FunctionEnum;
|
|
|
+use App\Enum\Core\ContactPointTypeEnum;
|
|
|
use App\Enum\Network\NetworkEnum;
|
|
|
+use App\Enum\Organization\AddressPostalOrganizationTypeEnum;
|
|
|
use App\Enum\Organization\OrganizationIdsEnum;
|
|
|
+use App\Enum\Organization\SettingsProductEnum;
|
|
|
+use App\Repository\Access\AccessRepository;
|
|
|
use App\Repository\Organization\OrganizationRepository;
|
|
|
+use App\Service\Core\AddressPostalUtils;
|
|
|
use App\Service\Dolibarr\DolibarrApiService;
|
|
|
+use Doctrine\ORM\EntityManager;
|
|
|
+use Doctrine\ORM\EntityManagerInterface;
|
|
|
+use Doctrine\ORM\QueryBuilder;
|
|
|
use Exception;
|
|
|
use HttpException;
|
|
|
+use libphonenumber\PhoneNumber;
|
|
|
+use libphonenumber\PhoneNumberFormat;
|
|
|
+use libphonenumber\PhoneNumberUtil;
|
|
|
|
|
|
/**
|
|
|
* Push the data from the Opentalent DB into the Dolibarr DB, trough both applications
|
|
|
@@ -21,7 +34,8 @@ class DolibarrSyncService
|
|
|
{
|
|
|
public function __construct(
|
|
|
private OrganizationRepository $organizationRepository,
|
|
|
- private DolibarrApiService $dolibarrApiService
|
|
|
+ private AccessRepository $accessRepository,
|
|
|
+ private DolibarrApiService $dolibarrApiService,
|
|
|
) {}
|
|
|
|
|
|
/**
|
|
|
@@ -38,107 +52,131 @@ class DolibarrSyncService
|
|
|
public function scan(): array {
|
|
|
|
|
|
// Index the dolibarr clients by organization ids
|
|
|
- $dolibarrClientsIndex = [];
|
|
|
- foreach ($this->dolibarrApiService->getAllClients() as $clientData) {
|
|
|
- if (!$clientData["array_options"]["2iopen_organization_id"] > 0) {
|
|
|
- $this->logScanError(
|
|
|
- "Missing organization id : " . $clientData["name"] . "(" . $clientData["code_client"] .")"
|
|
|
- );
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- $dolibarrClientsIndex[$clientData["organization_id"]] = $clientData;
|
|
|
- }
|
|
|
+ $dolibarrClientsIndex = $this->getDolibarrSocietiesIndex();
|
|
|
|
|
|
// Index the dolibarr contacts by person ids
|
|
|
- $dolibarrContactsIndex = [];
|
|
|
- foreach ($this->dolibarrApiService->getAllOpentalentContacts() as $contactData) {
|
|
|
- if (!$contactData["array_options"]["2iopen_person_id"] > 0) {
|
|
|
- $this->logScanError(
|
|
|
- "Missing person id : " . $contactData["name"] . "(" . $clientData["code_client"] .")"
|
|
|
- );
|
|
|
- continue;
|
|
|
- }
|
|
|
+ $dolibarrContactsIndex = $this->getDolibarrContactsIndex();
|
|
|
|
|
|
- $dolibarrContactsIndex[$contactData["organization_id"]] = $contactData;
|
|
|
- }
|
|
|
-
|
|
|
- // Loop over the Opentalent organizations, and create the operations list
|
|
|
+ // Loop over the Opentalent organizations, and fill up the operations list
|
|
|
$operations = [];
|
|
|
foreach ($this->organizationRepository->findAll() as $organization) {
|
|
|
- if (!isset($dolibarrClientsIndex["organization_id"])) {
|
|
|
+ if (!array_key_exists($organization->getId(), $dolibarrClientsIndex)) {
|
|
|
// this organization is not a client, probably a federation member
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- $dolibarrClient = $dolibarrClientsIndex[$organization->getId()];
|
|
|
+ $dolibarrSociety = $dolibarrClientsIndex[$organization->getId()];
|
|
|
+
|
|
|
+ $putSocietyData = [];
|
|
|
+
|
|
|
+ // ** Sync name
|
|
|
+ if ($organization->getName() !== $dolibarrSociety['name']) {
|
|
|
+ $putSocietyData['name'] = $organization->getName();
|
|
|
+ }
|
|
|
|
|
|
// ** Sync contact data of the client
|
|
|
// Postal address
|
|
|
/** @var AddressPostal | null */
|
|
|
- $mainAddress = null;
|
|
|
- foreach ($organization->getOrganizationAddressPostals() as $postalAddress) {
|
|
|
- if ($postalAddress->getType() == 'PRINCIPAL') {
|
|
|
- $mainAddress = $postalAddress->getAddress();
|
|
|
- }
|
|
|
- }
|
|
|
+ $mainAddress = $this->getOrganizationPostalAddress($organization);
|
|
|
|
|
|
if ($mainAddress !== null) {
|
|
|
- $params = [];
|
|
|
-
|
|
|
- $streetAddress = implode('\n', array_filter([
|
|
|
- trim($mainAddress->getStreetAddress()),
|
|
|
- trim($mainAddress->getStreetAddressSecond()),
|
|
|
- trim($mainAddress->getStreetAddressThird())
|
|
|
- ]), function ($x) { return $x !== null and strlen($x) > 0; });
|
|
|
-
|
|
|
- if ($streetAddress !== $dolibarrClient['address']) {
|
|
|
- $params['address'] = $streetAddress;
|
|
|
+ $streetAddress = AddressPostalUtils::getFullStreetAddress($mainAddress);
|
|
|
+ if (trim($mainAddress->getAddressOwner() ?? '') !== '') {
|
|
|
+ $streetAddress = 'Chez ' . $mainAddress->getAddressOwner() . '\n' . $streetAddress;
|
|
|
}
|
|
|
|
|
|
- if ($mainAddress->getPostalCode() !== $dolibarrClient['zip']) {
|
|
|
- $params['zip'] = $mainAddress->getPostalCode();
|
|
|
+ if ($streetAddress !== $dolibarrSociety['address']) {
|
|
|
+ $putSocietyData['address'] = $streetAddress;
|
|
|
}
|
|
|
|
|
|
- if ($mainAddress->getAddressCity() !== $dolibarrClient['town']) {
|
|
|
- $params['town'] = $mainAddress->getAddressCity();
|
|
|
+ if ($mainAddress->getPostalCode() !== $dolibarrSociety['zip']) {
|
|
|
+ $putSocietyData['zip'] = $mainAddress->getPostalCode();
|
|
|
}
|
|
|
|
|
|
- if ($params) {
|
|
|
- $operations[] = new DolibarrSyncOperation(
|
|
|
- 'Organization ' . $organization->getId() . ': update address ' .
|
|
|
- '(current: ' . $params['address'] . ' ' . $params['zip'] . ' ' . $params['town'] . ')',
|
|
|
- 'PUT',
|
|
|
- 'thirdparties/' . $dolibarrClient['id'],
|
|
|
- $params
|
|
|
- );
|
|
|
+ if ($mainAddress->getAddressCity() !== $dolibarrSociety['town']) {
|
|
|
+ $putSocietyData['town'] = $mainAddress->getAddressCity();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- // Network
|
|
|
- $network = $organization->getNetworkOrganizations()->first()->getNetwork();
|
|
|
- $parentOrganizationId = null;
|
|
|
+ // Sync contact
|
|
|
+ $email = $this->getOrganizationEmail($organization);
|
|
|
+ if ($email !== $dolibarrSociety['email']) {
|
|
|
+ $putSocietyData['email'] = $email;
|
|
|
+ }
|
|
|
|
|
|
- if ($network->getId() === NetworkEnum::CMF()) {
|
|
|
- $parentOrganizationId = OrganizationIdsEnum::CMF();
|
|
|
- } else if ($network->getId() === NetworkEnum::FFEC()) {
|
|
|
- $parentOrganizationId = OrganizationIdsEnum::FFEC();
|
|
|
- }
|
|
|
+ $phone = $this->getOrganizationPhone($organization);
|
|
|
+ if ($phone !== $dolibarrSociety['phone']) {
|
|
|
+ $putSocietyData['phone'] = $phone;
|
|
|
+ }
|
|
|
|
|
|
- if ($parentOrganizationId !== null) {
|
|
|
- $parent = $this->dolibarrApiService->getSociety($parentOrganizationId);
|
|
|
+ // ** Sync Network
|
|
|
+ $network = $organization->getNetworkOrganizations()->first()->getNetwork();
|
|
|
+ $parentOrganizationId = null;
|
|
|
|
|
|
- $operations[] = new DolibarrSyncOperation(
|
|
|
- 'Organization ' . $organization->getId() . ': update network ' .
|
|
|
- '(current: ' . $parent['parent'] . ')',
|
|
|
- 'PUT',
|
|
|
- 'thirdparties/' . $dolibarrClient['id'],
|
|
|
- ['parent' => $parent['id']]
|
|
|
- );
|
|
|
- }
|
|
|
+ if ($network->getId() === NetworkEnum::CMF()->getValue()) {
|
|
|
+ $parentOrganizationId = OrganizationIdsEnum::CMF()->getValue();
|
|
|
+ } else if ($network->getId() === NetworkEnum::FFEC()->getValue()) {
|
|
|
+ $parentOrganizationId = OrganizationIdsEnum::FFEC()->getValue();
|
|
|
+ } else {
|
|
|
+ $parentOrganizationId = OrganizationIdsEnum::_2IOS()->getValue();
|
|
|
+ }
|
|
|
|
|
|
-
|
|
|
+ $parent = $this->dolibarrApiService->getSociety($parentOrganizationId);
|
|
|
+ if ($parent['id'] !== $dolibarrSociety['parent']) {
|
|
|
+ $putSocietyData['parent'] = $parent['id'];
|
|
|
+ }
|
|
|
|
|
|
+ // More infos
|
|
|
+ $infosArray = [];
|
|
|
+
|
|
|
+ $product = $organization->getSettings()->getProduct();
|
|
|
+ if (
|
|
|
+ $product == SettingsProductEnum::SCHOOL()->getValue() ||
|
|
|
+ $product == SettingsProductEnum::SCHOOL_PREMIUM()->getValue()
|
|
|
+ ) {
|
|
|
+ $studentsCount = $this->accessRepository->countAccessesWithActiveMission(
|
|
|
+ $organization->getId(), FunctionEnum::STUDENT()->getValue()
|
|
|
+ );
|
|
|
+ $infosArray[] = "Nombre d'élèves : " . $studentsCount;
|
|
|
}
|
|
|
+
|
|
|
+ if (
|
|
|
+ $product == SettingsProductEnum::SCHOOL()->getValue() ||
|
|
|
+ $product == SettingsProductEnum::SCHOOL_PREMIUM()->getValue() ||
|
|
|
+ $product == SettingsProductEnum::ARTIST()->getValue() ||
|
|
|
+ $product == SettingsProductEnum::ARTIST_PREMIUM()->getValue()
|
|
|
+ ) {
|
|
|
+ $membersCount = $this->accessRepository->countAccessesWithActiveMission(
|
|
|
+ $organization->getId(), FunctionEnum::ADHERENT()->getValue()
|
|
|
+ );
|
|
|
+ $infosArray[] = "Nombre d'adhérents : " . $membersCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ $adminsCount = $this->accessRepository->countAdminAccounts(
|
|
|
+ $organization->getId()
|
|
|
+ );
|
|
|
+ $infosArray[] = "Nombre d'accès admin : " . $adminsCount;
|
|
|
+
|
|
|
+ $infos = implode('\n', $infosArray);
|
|
|
+ if ($infos !== $dolibarrSociety["array_options"]["options_2iopeninfoopentalent"]) {
|
|
|
+ // /!\ On est forcé de passer la sub-array entière pour mettre à jour le champs modifié, sinon
|
|
|
+ // tous les autres champs seront mis à null...
|
|
|
+ $arrayOptions = $dolibarrSociety["array_options"];
|
|
|
+ $arrayOptions['options_2iopeninfoopentalent'] = $infos;
|
|
|
+ $putSocietyData['array_options'] = $arrayOptions;
|
|
|
+ }
|
|
|
+
|
|
|
+ $operations[] = new DolibarrSyncOperation(
|
|
|
+ 'Update organization ' . $organization->getId() . ' - ' . $organization->getName(),
|
|
|
+ 'PUT',
|
|
|
+ 'thirdparties/' . $dolibarrSociety['id'],
|
|
|
+ $putSocietyData,
|
|
|
+ $dolibarrSociety
|
|
|
+ );
|
|
|
+
|
|
|
+ // ** Contacts
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
return $operations;
|
|
|
@@ -189,4 +227,137 @@ class DolibarrSyncService
|
|
|
private function logScanError($errorMsg) {
|
|
|
// TODO : implement
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get the client societies dolibarr and index it by organization id
|
|
|
+ *
|
|
|
+ * @return array An index of the form [$organizationId => $dolibarrData]
|
|
|
+ * @throws HttpException
|
|
|
+ */
|
|
|
+ private function getDolibarrSocietiesIndex(): array
|
|
|
+ {
|
|
|
+ $index = [];
|
|
|
+ foreach ($this->dolibarrApiService->getAllClients() as $clientData) {
|
|
|
+ if (!$clientData["array_options"]["options_2iopen_organization_id"] > 0) {
|
|
|
+ $this->logScanError(
|
|
|
+ "Missing organization id : " . $clientData["name"] . "(" . $clientData["code_client"] .")"
|
|
|
+ );
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ $index[$clientData["array_options"]["options_2iopen_organization_id"]] = $clientData;
|
|
|
+ }
|
|
|
+ return $index;
|
|
|
+ }
|
|
|
+
|
|
|
+ private function getDolibarrContactsIndex(): array {
|
|
|
+ $index = [];
|
|
|
+ foreach ($this->dolibarrApiService->getAllOpentalentContacts() as $contactData) {
|
|
|
+ if (!$contactData["array_options"]["options_2iopen_person_id"] > 0) {
|
|
|
+ $this->logScanError(
|
|
|
+ "Missing person id : " . $contactData["lastname"] . " " . $contactData["firstname"] . "(id:" . $contactData["id"] .")"
|
|
|
+ );
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ $index[$contactData["array_options"]["options_2iopen_person_id"]] = $contactData;
|
|
|
+ }
|
|
|
+
|
|
|
+ return $index;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Retrieve the postal address of the organization
|
|
|
+ *
|
|
|
+ * @param Organization $organization
|
|
|
+ * @return null
|
|
|
+ */
|
|
|
+ private function getOrganizationPostalAddress(Organization $organization) {
|
|
|
+ $addressPriorities = [
|
|
|
+ AddressPostalOrganizationTypeEnum::ADDRESS_BILL()->getValue(),
|
|
|
+ AddressPostalOrganizationTypeEnum::ADDRESS_CONTACT()->getValue(),
|
|
|
+ AddressPostalOrganizationTypeEnum::ADDRESS_HEAD_OFFICE()->getValue(),
|
|
|
+ AddressPostalOrganizationTypeEnum::ADDRESS_PRACTICE()->getValue(),
|
|
|
+ AddressPostalOrganizationTypeEnum::ADDRESS_OTHER()->getValue()
|
|
|
+ ];
|
|
|
+
|
|
|
+ foreach ($addressPriorities as $addressType) {
|
|
|
+ foreach ($organization->getOrganizationAddressPostals() as $postalAddress) {
|
|
|
+ if ($postalAddress->getType() == $addressType) {
|
|
|
+ return $postalAddress->getAddressPostal();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Retrieve the phone for the organization
|
|
|
+ *
|
|
|
+ * @param Organization $organization
|
|
|
+ * @return null
|
|
|
+ */
|
|
|
+ private function getOrganizationPhone(Organization $organization) {
|
|
|
+ $contactPriorities = [
|
|
|
+ ContactPointTypeEnum::BILL()->getValue(),
|
|
|
+ ContactPointTypeEnum::CONTACT()->getValue(),
|
|
|
+ ContactPointTypeEnum::PRINCIPAL()->getValue(),
|
|
|
+ ContactPointTypeEnum::OTHER()->getValue()
|
|
|
+ ];
|
|
|
+
|
|
|
+ foreach ($contactPriorities as $contactType) {
|
|
|
+ foreach ($organization->getContactPoints() as $contactPoint) {
|
|
|
+ if ($contactPoint->getContactType() == $contactType) {
|
|
|
+ if ($contactPoint->getTelphone() !== null) {
|
|
|
+ return $this->formatPhoneNumber($contactPoint->getTelphone());
|
|
|
+ }
|
|
|
+ if ($contactPoint->getMobilPhone() !== null) {
|
|
|
+ return $this->formatPhoneNumber($contactPoint->getMobilPhone());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Retrieve the email for the organization
|
|
|
+ *
|
|
|
+ * @param Organization $organization
|
|
|
+ * @return null
|
|
|
+ */
|
|
|
+ private function getOrganizationEmail(Organization $organization) {
|
|
|
+ $contactPriorities = [
|
|
|
+ ContactPointTypeEnum::BILL()->getValue(),
|
|
|
+ ContactPointTypeEnum::CONTACT()->getValue(),
|
|
|
+ ContactPointTypeEnum::PRINCIPAL()->getValue(),
|
|
|
+ ContactPointTypeEnum::OTHER()->getValue()
|
|
|
+ ];
|
|
|
+
|
|
|
+ foreach ($contactPriorities as $contactType) {
|
|
|
+ foreach ($organization->getContactPoints() as $contactPoint) {
|
|
|
+ if ($contactPoint->getContactType() == $contactType && $contactPoint->getEmail() !== null) {
|
|
|
+ return $contactPoint->getEmail();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Formatte un numéro de téléphone, au format français si l'indicatif national
|
|
|
+ * est l'indicatif français ou s'il est manquant,
|
|
|
+ * au format international sinon.
|
|
|
+ *
|
|
|
+ * @param PhoneNumber $phoneNumber
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ private function formatPhoneNumber(PhoneNumber $phoneNumber): string {
|
|
|
+ $phoneUtil = PhoneNumberUtil::getInstance();
|
|
|
+ if (!$phoneNumber->hasCountryCode() || $phoneNumber->getCountryCode() == 33) {
|
|
|
+ return $phoneUtil->format($phoneNumber, PhoneNumberFormat::NATIONAL);
|
|
|
+ } else {
|
|
|
+ return $phoneUtil->format($phoneNumber, PhoneNumberFormat::INTERNATIONAL);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|