|
|
@@ -2,7 +2,6 @@
|
|
|
|
|
|
namespace App\Service\Dolibarr\DolibarrSync;
|
|
|
|
|
|
-use App\Entity\Access\Access;
|
|
|
use App\Entity\Core\AddressPostal;
|
|
|
use App\Entity\Organization\Organization;
|
|
|
use App\Enum\Access\FunctionEnum;
|
|
|
@@ -12,12 +11,10 @@ use App\Enum\Organization\AddressPostalOrganizationTypeEnum;
|
|
|
use App\Enum\Organization\OrganizationIdsEnum;
|
|
|
use App\Enum\Organization\SettingsProductEnum;
|
|
|
use App\Repository\Access\AccessRepository;
|
|
|
+use App\Repository\Core\ContactPointRepository;
|
|
|
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;
|
|
|
@@ -32,9 +29,11 @@ use libphonenumber\PhoneNumberUtil;
|
|
|
*/
|
|
|
class DolibarrSyncService
|
|
|
{
|
|
|
+
|
|
|
public function __construct(
|
|
|
private OrganizationRepository $organizationRepository,
|
|
|
private AccessRepository $accessRepository,
|
|
|
+ private ContactPointRepository $contactPointRepository,
|
|
|
private DolibarrApiService $dolibarrApiService,
|
|
|
) {}
|
|
|
|
|
|
@@ -54,8 +53,8 @@ class DolibarrSyncService
|
|
|
// Index the dolibarr clients by organization ids
|
|
|
$dolibarrClientsIndex = $this->getDolibarrSocietiesIndex();
|
|
|
|
|
|
- // Index the dolibarr contacts by person ids
|
|
|
- $dolibarrContactsIndex = $this->getDolibarrContactsIndex();
|
|
|
+ // Get all active accesses
|
|
|
+ $membersIndex = $this->getActiveMembersIndex();
|
|
|
|
|
|
// Loop over the Opentalent organizations, and fill up the operations list
|
|
|
$operations = [];
|
|
|
@@ -67,6 +66,13 @@ class DolibarrSyncService
|
|
|
|
|
|
$dolibarrSociety = $dolibarrClientsIndex[$organization->getId()];
|
|
|
|
|
|
+ // Populate the expectedContacts array
|
|
|
+ if (array_key_exists($organization->getId(), $membersIndex)) {
|
|
|
+ $organizationMembers = $membersIndex[$organization->getId()];
|
|
|
+ } else {
|
|
|
+ $organizationMembers = [];
|
|
|
+ }
|
|
|
+
|
|
|
$putSocietyData = [];
|
|
|
|
|
|
// ** Sync name
|
|
|
@@ -134,9 +140,10 @@ class DolibarrSyncService
|
|
|
$product == SettingsProductEnum::SCHOOL()->getValue() ||
|
|
|
$product == SettingsProductEnum::SCHOOL_PREMIUM()->getValue()
|
|
|
) {
|
|
|
- $studentsCount = $this->accessRepository->countAccessesWithActiveMission(
|
|
|
- $organization->getId(), FunctionEnum::STUDENT()->getValue()
|
|
|
- );
|
|
|
+ $studentsCount = count(array_filter(
|
|
|
+ $organizationMembers,
|
|
|
+ function ($missions) { return in_array(FunctionEnum::STUDENT()->getValue(), $missions); }
|
|
|
+ ));
|
|
|
$infosArray[] = "Nombre d'élèves : " . $studentsCount;
|
|
|
}
|
|
|
|
|
|
@@ -146,15 +153,19 @@ class DolibarrSyncService
|
|
|
$product == SettingsProductEnum::ARTIST()->getValue() ||
|
|
|
$product == SettingsProductEnum::ARTIST_PREMIUM()->getValue()
|
|
|
) {
|
|
|
- $membersCount = $this->accessRepository->countAccessesWithActiveMission(
|
|
|
- $organization->getId(), FunctionEnum::ADHERENT()->getValue()
|
|
|
- );
|
|
|
+ $membersCount = count(array_filter(
|
|
|
+ $organizationMembers,
|
|
|
+ function ($missions) { return in_array(FunctionEnum::ADHERENT()->getValue(), $missions); }
|
|
|
+ ));
|
|
|
$infosArray[] = "Nombre d'adhérents : " . $membersCount;
|
|
|
}
|
|
|
|
|
|
- $adminsCount = $this->accessRepository->countAdminAccounts(
|
|
|
- $organization->getId()
|
|
|
- );
|
|
|
+ $adminsCount = count($this->accessRepository->findBy(
|
|
|
+ [
|
|
|
+ 'organization' => $organization,
|
|
|
+ 'adminAccess' => true
|
|
|
+ ]
|
|
|
+ ));
|
|
|
$infosArray[] = "Nombre d'accès admin : " . $adminsCount;
|
|
|
|
|
|
$infos = implode('\n', $infosArray);
|
|
|
@@ -175,8 +186,164 @@ class DolibarrSyncService
|
|
|
);
|
|
|
|
|
|
// ** Contacts
|
|
|
+ $officeMissions = [
|
|
|
+ FunctionEnum::PRESIDENT()->getValue(),
|
|
|
+ FunctionEnum::SECRETARY()->getValue(),
|
|
|
+ FunctionEnum::TREASURER()->getValue(),
|
|
|
+ FunctionEnum::ADMINISTRATIVE_OFFICER()->getValue(),
|
|
|
+ FunctionEnum::ADMINISTRATIVE_SECRETARY()->getValue(),
|
|
|
+ FunctionEnum::ADMINISTRATIVE_DIRECTOR()->getValue(),
|
|
|
+ FunctionEnum::ADMINISTRATIVE_STAFF()->getValue()
|
|
|
+ ];
|
|
|
+
|
|
|
+ $rolesLabels = [
|
|
|
+ 'MISS' => [
|
|
|
+ FunctionEnum::PRESIDENT()->getValue() => 'Présidente',
|
|
|
+ FunctionEnum::SECRETARY()->getValue() => 'Secrétaire',
|
|
|
+ FunctionEnum::TREASURER()->getValue() => 'Trésorière',
|
|
|
+ FunctionEnum::ADMINISTRATIVE_OFFICER()->getValue() => 'Responsable admin.',
|
|
|
+ FunctionEnum::ADMINISTRATIVE_SECRETARY()->getValue() => 'Secrétaire admin.',
|
|
|
+ FunctionEnum::ADMINISTRATIVE_DIRECTOR()->getValue() => 'Directrice',
|
|
|
+ FunctionEnum::ADMINISTRATIVE_STAFF()->getValue() => 'Personnel administratif'
|
|
|
+ ],
|
|
|
+ 'MISTER' => [
|
|
|
+ FunctionEnum::PRESIDENT()->getValue() => 'Président',
|
|
|
+ FunctionEnum::SECRETARY()->getValue() => 'Secrétaire',
|
|
|
+ FunctionEnum::TREASURER()->getValue() => 'Trésorier',
|
|
|
+ FunctionEnum::ADMINISTRATIVE_OFFICER()->getValue() => 'Responsable admin.',
|
|
|
+ FunctionEnum::ADMINISTRATIVE_SECRETARY()->getValue() => 'Secrétaire admin.',
|
|
|
+ FunctionEnum::ADMINISTRATIVE_DIRECTOR()->getValue() => 'Directeur',
|
|
|
+ FunctionEnum::ADMINISTRATIVE_STAFF()->getValue() => 'Personnel administratif'
|
|
|
+ ]
|
|
|
+ ];
|
|
|
+
|
|
|
+ $dolibarrContactsIndex = $this->getDolibarrContactsIndex($dolibarrSociety['id']);
|
|
|
+ $contactsProcessed = [];
|
|
|
+
|
|
|
+ foreach ($organizationMembers as $accessId => $missions) {
|
|
|
+ foreach ($missions as $mission) {
|
|
|
+ if (in_array($mission, $officeMissions)) {
|
|
|
+ $access = $this->accessRepository->find($accessId);
|
|
|
+ $person = $access->getPerson();
|
|
|
+
|
|
|
+ if (in_array($person->getId(), $contactsProcessed)) {
|
|
|
+ // already updated from another mission
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $contactsProcessed[] = $person->getId();
|
|
|
+
|
|
|
+ if (array_key_exists($person->getId(), $dolibarrContactsIndex)) {
|
|
|
+ $dolibarrContact = $dolibarrContactsIndex[$person->getId()];
|
|
|
+ } else {
|
|
|
+ // new contact
|
|
|
+ $dolibarrContact = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ $putContactData = [];
|
|
|
+
|
|
|
+ $contactRes = $this->contactPointRepository->getByTypeAndPerson(
|
|
|
+ ContactPointTypeEnum::PRINCIPAL()->getValue(), $person
|
|
|
+ );
|
|
|
+ if (empty($contactRes)) {
|
|
|
+ $contactRes = $this->contactPointRepository->getByTypeAndPerson(
|
|
|
+ ContactPointTypeEnum::OTHER()->getValue(), $person
|
|
|
+ );
|
|
|
+ }
|
|
|
+ $contact = empty($contactRes) ? null : $contactRes[0];
|
|
|
+
|
|
|
+ $lastname = $person->getName();
|
|
|
+ $firstname = $person->getGivenName();
|
|
|
+ $email = $contact?->getEmail();
|
|
|
+ $phone = null;
|
|
|
+ if ($contact !== null && $contact->getTelphone() !== null) {
|
|
|
+ $phone = $this->formatPhoneNumber($contact->getTelphone());
|
|
|
+ }
|
|
|
+ $mobilePhone = null;
|
|
|
+ if ($contact !== null && $contact->getMobilPhone() !== null) {
|
|
|
+ $mobilePhone = $this->formatPhoneNumber($contact->getMobilPhone());
|
|
|
+ }
|
|
|
+ $civility = $person->getGender() === 'MISS' ? 'Mrs.' : 'Mr.';
|
|
|
+ $poste = implode(
|
|
|
+ ', ',
|
|
|
+ array_map(
|
|
|
+ function($m) use ($rolesLabels, $person) {
|
|
|
+ return $rolesLabels[$person->getGender() ?? 'MISTER'][$m];
|
|
|
+ },
|
|
|
+ array_filter(
|
|
|
+ $missions,
|
|
|
+ function($m) use ($officeMissions){ return in_array($m, $officeMissions); }
|
|
|
+ )
|
|
|
+ )
|
|
|
+ );
|
|
|
+
|
|
|
+ if ($dolibarrContact === null) {
|
|
|
+ $postContactData = [
|
|
|
+ 'civility' => $civility,
|
|
|
+ 'lastname' => $lastname,
|
|
|
+ 'firstname' => $firstname,
|
|
|
+ 'email' => $email,
|
|
|
+ 'phone_pro' => $phone,
|
|
|
+ 'phone_mobile' => $mobilePhone,
|
|
|
+ 'poste' => $poste
|
|
|
+ ];
|
|
|
+
|
|
|
+ $operations[] = new DolibarrSyncOperation(
|
|
|
+ 'Create person ' . $person->getId() . ' - ' . $person->getName() . ' ' . $person->getGivenName(),
|
|
|
+ 'POST',
|
|
|
+ 'contacts',
|
|
|
+ $postContactData
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ if ($civility !== $dolibarrContact['civility']) {
|
|
|
+ $putContactData['civility'] = $civility;
|
|
|
+ }
|
|
|
+ if ($lastname !== $dolibarrContact['lastname']) {
|
|
|
+ $putContactData['lastname'] = $lastname;
|
|
|
+ }
|
|
|
+ if ($firstname !== $dolibarrContact['firstname']) {
|
|
|
+ $putContactData['firstname'] = $firstname;
|
|
|
+ }
|
|
|
+ if ($email !== $dolibarrContact['email']) {
|
|
|
+ $putContactData['email'] = $contact->getEmail();
|
|
|
+ }
|
|
|
+ // the dolibarr api return an empty string even if the field is null
|
|
|
+ if ($phone !== $dolibarrContact['phone_pro'] && $dolibarrContact['phone_pro'] !== '') {
|
|
|
+ $putContactData['phone_pro'] = $phone;
|
|
|
+ }
|
|
|
+ // the dolibarr api return an empty string even if the field is null
|
|
|
+ if ($mobilePhone !== $dolibarrContact['phone_mobile'] && $dolibarrContact['phone_mobile'] !== '') {
|
|
|
+ $putContactData['phone_mobile'] = $mobilePhone;
|
|
|
+ }
|
|
|
+ if ($poste !== $dolibarrContact['poste']) {
|
|
|
+ $putContactData['poste'] = $poste;
|
|
|
+ }
|
|
|
+
|
|
|
+ $operations[] = new DolibarrSyncOperation(
|
|
|
+ 'Update person ' . $person->getId() . ' - ' . $person->getName() . ' ' . $person->getGivenName(),
|
|
|
+ 'PUT',
|
|
|
+ 'contacts/' . $dolibarrContact['id'],
|
|
|
+ $putContactData,
|
|
|
+ $dolibarrContact
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // No need to test the other missions of this access
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-
|
|
|
+ foreach ($dolibarrContactsIndex as $personId => $contactData) {
|
|
|
+ if (!in_array($personId, $contactsProcessed)) {
|
|
|
+ // Ce personId n'existe plus dans les membres Opentalent de cette société, on delete
|
|
|
+ $operations[] = new DolibarrSyncOperation(
|
|
|
+ 'Delete person ' . $personId . ' - ' . $person->getName() . ' ' . $person->getGivenName() .
|
|
|
+ ' from the contacts of organization ' . $organization->getId() . ' - ' . $organization->getName(),
|
|
|
+ 'DELETE',
|
|
|
+ 'contacts/' . $contactData['id']
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return $operations;
|
|
|
@@ -229,7 +396,7 @@ class DolibarrSyncService
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Get the client societies dolibarr and index it by organization id
|
|
|
+ * Get the client societies dolibarr and index them by organization id
|
|
|
*
|
|
|
* @return array An index of the form [$organizationId => $dolibarrData]
|
|
|
* @throws HttpException
|
|
|
@@ -250,19 +417,44 @@ class DolibarrSyncService
|
|
|
return $index;
|
|
|
}
|
|
|
|
|
|
- private function getDolibarrContactsIndex(): array {
|
|
|
+ /**
|
|
|
+ * Get the dolibarr contacts of the society and index them by person_id
|
|
|
+ *
|
|
|
+ * @return array An index of the form [$personId => $dolibarrData]
|
|
|
+ */
|
|
|
+ private function getDolibarrContactsIndex(int $socId): 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;
|
|
|
+ $contacts = $this->dolibarrApiService->getOpentalentContacts($socId);
|
|
|
+ foreach ($contacts as $contactData) {
|
|
|
+ $personId = intval($contactData["array_options"]["options_2iopen_person_id"]);
|
|
|
+ $index[$personId] = $contactData;
|
|
|
}
|
|
|
+ return $index;
|
|
|
+ }
|
|
|
|
|
|
+ /**
|
|
|
+ * Returns an index of all the active members with their current mission(s)
|
|
|
+ *
|
|
|
+ * Index is the form: [$organizationId => [$accessId => [$mission, $mission...], $accessId...], $organizationId2...]
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ private function getActiveMembersIndex(): array {
|
|
|
+ $index = [];
|
|
|
+ $results = $this->accessRepository->getAllActiveMembersAndMissions();
|
|
|
+ foreach ($results as $row) {
|
|
|
+ $accessId = $row['id'];
|
|
|
+ $organizationId = $row['organization_id'];
|
|
|
+ $mission = $row['mission'];
|
|
|
+
|
|
|
+ if (!array_key_exists($organizationId, $index)) {
|
|
|
+ $index[$organizationId] = [];
|
|
|
+ }
|
|
|
+ if (!array_key_exists($accessId, $index[$organizationId])) {
|
|
|
+ $index[$organizationId][$accessId] = [];
|
|
|
+ }
|
|
|
+ $index[$organizationId][$accessId][] = $mission;
|
|
|
+ }
|
|
|
return $index;
|
|
|
}
|
|
|
|
|
|
@@ -295,9 +487,10 @@ class DolibarrSyncService
|
|
|
* Retrieve the phone for the organization
|
|
|
*
|
|
|
* @param Organization $organization
|
|
|
- * @return null
|
|
|
+ * @return string|null
|
|
|
*/
|
|
|
- private function getOrganizationPhone(Organization $organization) {
|
|
|
+ private function getOrganizationPhone(Organization $organization): ?string
|
|
|
+ {
|
|
|
$contactPriorities = [
|
|
|
ContactPointTypeEnum::BILL()->getValue(),
|
|
|
ContactPointTypeEnum::CONTACT()->getValue(),
|