diff --git a/VERSIONS_HOTLINE/192556 b/VERSIONS_HOTLINE/192556
new file mode 100644
index 0000000000000000000000000000000000000000..db778994f83c07c2d16fbb4b8c4d053b5aa8b97e
--- /dev/null
+++ b/VERSIONS_HOTLINE/192556
@@ -0,0 +1 @@
+ - correctif #192556 : Abonné : Correctif la suppression d'une notice d'un panier ne fonctionnait pas quand cette notice était lié à des ressources numériques.
\ No newline at end of file
diff --git a/library/Class/PanierNotice/RecordKeys.php b/library/Class/PanierNotice/RecordKeys.php
index 3b2baeedf9e75e3d6257fc9364436341610fc408..3fec288fb798d4f087306be30a50a8c797380bcb 100644
--- a/library/Class/PanierNotice/RecordKeys.php
+++ b/library/Class/PanierNotice/RecordKeys.php
@@ -20,15 +20,17 @@
  */
 
 
-class Class_PanierNotice_RecordKeys {
+class Class_PanierNotice_RecordKeys
+{
+
   const KEY_SEPARATOR = ';';
 
   protected static $_panier_record_keys_cache = [];
 
   protected array $_keys = [];
 
-
-  public function __construct(Class_PanierNotice $selection) {
+  public function __construct(Class_PanierNotice $selection)
+  {
     $keys = array_map('trim',
                       explode(static::KEY_SEPARATOR, $selection->getNotices()));
     $keys = array_filter(array_values(array_unique($keys)));
@@ -37,13 +39,15 @@ class Class_PanierNotice_RecordKeys {
   }
 
 
-  public function add(Class_Notice $record) : string {
+  public function add(Class_Notice $record): string
+  {
     $this->_keys[] = $this->_keyFor($record);
     return $this->serialized();
   }
 
 
-  public function remove(Class_Notice $record) : string {
+  public function remove(Class_Notice $record): string
+  {
     $record_key = $this->_keyFor($record);
     $this->_keys = array_filter($this->_keys,
                                 fn($key) => !$key->isSameAs($record_key));
@@ -52,13 +56,15 @@ class Class_PanierNotice_RecordKeys {
   }
 
 
-  public function keys() : array {
+  public function keys(): array
+  {
     return array_map(fn($key) => $key->keyOnly(),
                      $this->_keys);
   }
 
 
-  public function contains(Class_Notice $record) : bool {
+  public function contains(Class_Notice $record): bool
+  {
     $record_key = $this->_keyFor($record);
 
     return 0 < count(array_filter($this->_keys,
@@ -66,14 +72,16 @@ class Class_PanierNotice_RecordKeys {
   }
 
 
-  public function serialized() : string {
+  public function serialized(): string
+  {
     return implode(static::KEY_SEPARATOR,
                    array_map(fn($key) => $key->serialized(),
                              $this->_keys));
   }
 
 
-  protected function _keyFor(Class_Notice $record) : Class_PanierNotice_RecordKey {
+  protected function _keyFor(Class_Notice $record): Class_PanierNotice_RecordKey
+  {
     $record_id = $record->getId();
     if (isset(static::$_panier_record_keys_cache [$record_id]))
       return static::$_panier_record_keys_cache [$record_id];
@@ -82,7 +90,8 @@ class Class_PanierNotice_RecordKeys {
   }
 
 
-  public static function reset() {
+  public static function reset()
+  {
     static::$_panier_record_keys_cache = [];
   }
 }
@@ -90,14 +99,16 @@ class Class_PanierNotice_RecordKeys {
 
 
 
-abstract class Class_PanierNotice_RecordKey {
+abstract class Class_PanierNotice_RecordKey
+{
+
   const MODEL_SEPARATOR = '/';
   const ID_SEPARATOR = '@';
 
   protected string $_key;
 
-
-  public static function newFromKey(string $key) : self {
+  public static function newFromKey(string $key): self
+  {
     $parts = explode(static::MODEL_SEPARATOR, $key);
     return (1 === count($parts))
       ? static::_newExternal($key)
@@ -105,7 +116,8 @@ abstract class Class_PanierNotice_RecordKey {
   }
 
 
-  public static function newFromRecord(Class_Notice $record) : self {
+  public static function newFromRecord(Class_Notice $record): self
+  {
     $key = $record->getClefAlpha();
 
     return ($model = static::_detectModel($record))
@@ -114,8 +126,9 @@ abstract class Class_PanierNotice_RecordKey {
   }
 
 
-  protected static function _detectModel(Class_Notice $record) : ?Storm_Model_Abstract {
-    foreach(['getAlbum', 'getArticle', 'getPage', 'getSite', 'getRss'] as $method)
+  protected static function _detectModel(Class_Notice $record): ?Storm_Model_Abstract
+  {
+    foreach (['getAlbum', 'getArticle', 'getPage', 'getSite', 'getRss'] as $method)
       if ($model = $record->$method())
         return $model;
 
@@ -123,27 +136,32 @@ abstract class Class_PanierNotice_RecordKey {
   }
 
 
-  protected static function _newInternal(array $parts) : Class_PanierNotice_RecordKeyInternal {
+  protected static function _newInternal(array $parts): Class_PanierNotice_RecordKeyInternal
+  {
     return new Class_PanierNotice_RecordKeyInternal($parts);
   }
 
 
-  protected static function _newExternal(string $key) : Class_PanierNotice_RecordKeyExternal {
+  protected static function _newExternal(string $key): Class_PanierNotice_RecordKeyExternal
+  {
     return new Class_PanierNotice_RecordKeyExternal($key);
   }
 
 
-  public function serialized() : string {
+  public function serialized(): string
+  {
     return $this->_key;
   }
 
 
-  public function keyOnly() : string {
+  public function keyOnly(): string
+  {
     return $this->_key;
   }
 
 
-  public function isSameAs(Class_PanierNotice_RecordKey $other) : bool {
+  public function isSameAs(Class_PanierNotice_RecordKey $other): bool
+  {
     return $this->_key === $other->_key;
   }
 }
@@ -151,9 +169,11 @@ abstract class Class_PanierNotice_RecordKey {
 
 
 
-class Class_PanierNotice_RecordKeyExternal extends Class_PanierNotice_RecordKey {
+class Class_PanierNotice_RecordKeyExternal extends Class_PanierNotice_RecordKey
+{
 
-  public function __construct(string $key) {
+  public function __construct(string $key)
+  {
     if (Class_Notice::countBy(['clef_alpha' => $key])) {
       $this->_key = $key;
       return;
@@ -168,11 +188,14 @@ class Class_PanierNotice_RecordKeyExternal extends Class_PanierNotice_RecordKey
 
 
 
-class Class_PanierNotice_RecordKeyInternal extends Class_PanierNotice_RecordKey {
+class Class_PanierNotice_RecordKeyInternal extends Class_PanierNotice_RecordKey
+{
 
-  protected string $_model_info;
+  protected string $_model_info = '';
+  protected bool $_with_model_info = false;
 
-  public function __construct(array $parts) {
+  public function __construct(array $parts)
+  {
     $this->_key = $parts[0] ?? '';
     $this->_model_info = $parts[1] ?? '';
 
@@ -183,21 +206,49 @@ class Class_PanierNotice_RecordKeyInternal extends Class_PanierNotice_RecordKey
     if (2 !== count($model_parts))
       return;
 
-    try {
-      $model_class = $model_parts[0] ?? '';
-      $model_id = $model_parts[1] ?? 0;
-      if ($model_id && $model = $model_class::find($model_id))
-        $this->_key = (new Class_Notice_ClefAlpha($model))->keyString();
-    } catch(Exception $e) {}
+    $this->_keyForModelParts($model_parts);
   }
 
 
-  public function serialized() : string {
+  public function serialized(): string
+  {
     return parent::serialized() . static::MODEL_SEPARATOR . $this->_model_info;
   }
 
 
-  public function isSameAs(Class_PanierNotice_RecordKey $other) : bool {
-    return isset($other->_model_info) && $this->_model_info === $other->_model_info;
+  public function isSameAs(Class_PanierNotice_RecordKey $other): bool
+  {
+    return $this->_with_model_info
+      ? parent::isSameAs($other) && $this->_model_info === $other->_model_info
+      : parent::isSameAs($other);
+  }
+
+
+  protected function _keyForModelParts(array $model_parts): self
+  {
+    $model_class = $model_parts[0] ?? '';
+    $model_id = $model_parts[1] ?? 0;
+
+    if ($model = $this->_findForClassNameWithId($model_id, $model_class)) {
+      $this->_key = (new Class_Notice_ClefAlpha($model))->keyString();
+      $this->_with_model_info = true;
+    }
+
+    return $this;
+  }
+
+
+  protected function _findForClassNameWithId(int $id, string $class_name): ?Storm_Model_Abstract
+  {
+    if ( ! $id || ! $class_name)
+      return null;
+
+    try {
+      return (Class_Album::class === $class_name)
+        ? ($class_name::find($id) ?? $class_name::findFirstBy(['id_origine' => $id]))
+        : $class_name::find($id);
+    } catch(Exception $e) {
+      return null;
+    }
   }
 }
diff --git a/tests/application/modules/opac/controllers/AbonneControllerPaniersTest.php b/tests/application/modules/opac/controllers/AbonneControllerPaniersTest.php
index 007beb22092dfb824593b79c248c7da5d667ad9e..6276de6101e8ed76d4bc7803b17ec097584f32e3 100644
--- a/tests/application/modules/opac/controllers/AbonneControllerPaniersTest.php
+++ b/tests/application/modules/opac/controllers/AbonneControllerPaniersTest.php
@@ -19,18 +19,21 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 
-class AbonneControllerPaniersForMarcusTest extends AbstractControllerTestCase {
+
+class AbonneControllerPaniersForMarcusTest extends AbstractControllerTestCase
+{
+
   protected
-    $_storm_default_to_volatile = true,
     $marcus,
     $_xpath,
     $_json,
     $panier_bd;
 
-  public function setup() {
+  public function setup()
+  {
     parent::setup();
 
-    $this->marcus = $this->fixture('Class_Users',
+    $this->marcus = $this->fixture(Class_Users::class,
                                    ['id' => 45,
                                     'idabon' => 45,
                                     'login' => 'marcus',
@@ -38,7 +41,7 @@ class AbonneControllerPaniersForMarcusTest extends AbstractControllerTestCase {
                                     'prenom' => 'marcus',
                                     'nom' => 'bond']);
 
-    $marcel = $this->fixture('Class_Users',
+    $marcel = $this->fixture(Class_Users::class,
                              ['id' => 47,
                               'login' => 'marcel',
                               'password' => 'secret',
@@ -46,7 +49,7 @@ class AbonneControllerPaniersForMarcusTest extends AbstractControllerTestCase {
                               'nom' => 'doob']);
     $marcel->beAdminPortail()->assertSave();
 
-    $coups_coeur_marcel = $this->fixture('Class_PanierNotice',
+    $coups_coeur_marcel = $this->fixture(Class_PanierNotice::class,
                                          ['id' => 4,
                                           'id_panier' => 2,
                                           'libelle' => 'Mes coups de coeur',
@@ -54,16 +57,14 @@ class AbonneControllerPaniersForMarcusTest extends AbstractControllerTestCase {
                                           'notices' => 'POMME API',
                                           'user' => $marcel]);
 
-    $domaine_coups_coeur = $this->fixture('Class_Catalogue',
+    $domaine_coups_coeur = $this->fixture(Class_Catalogue::class,
                                           ['id' => 1,
                                            'libelle' => 'Coups de coeur',
                                            'panier_notices' => [$coups_coeur_marcel]]);
 
-
-
     ZendAfi_Auth::getInstance()->logUser($this->marcus);
 
-    $this->panier_bd = $this->fixture('Class_PanierNotice',
+    $this->panier_bd = $this->fixture(Class_PanierNotice::class,
                                       ['id' => 2,
                                        'id_panier' => 1,
                                        'libelle' => 'Mes BD',
@@ -71,82 +72,196 @@ class AbonneControllerPaniersForMarcusTest extends AbstractControllerTestCase {
                                        'notices' => 'COMBAT ORDINAIRE;BLACKSAD',
                                        'user' => $this->marcus]);
 
-
-    Storm_Test_ObjectWrapper::onLoaderOfModel('Class_PanierNotice')
+    Storm_Test_ObjectWrapper::onLoaderOfModel(Class_PanierNotice::class)
       ->whenCalled('findAllBy')
       ->answers([$this->panier_bd]);
 
-    Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Catalogue')
+    Storm_Test_ObjectWrapper::onLoaderOfModel(Class_Catalogue::class)
       ->whenCalled('findTopCatalogues')
       ->answers([$domaine_coups_coeur]);
   }
 
 
   /** @test **/
-  public function getPaniersAsAdminShouldReturnMarcusPanierAsJSON() {
+  public function getPaniersAsAdminShouldReturnMarcusPanierAsJSON()
+  {
     $this->marcus->beModoBib();
 
-    $this->dispatch('abonne/get-paniers.json',true);
-
-    $this->assertJsonStringEqualsJsonString(
-      $this->_response->getBody(),
-      json_encode([
-                    ["id" => "panier_for_user",
-                     "label" => "Mes paniers",
-                     "categories" => [],
-                     "items" => [
-                       ["id" => 2,
-                        "label" => "Mes BD",
-                        "options" => ["ico" => BASE_URL."/public/admin/images/picto/paniers_16.png"]]],
-                     "options" => ["multipleSelection" => false]],
-
-                    [
-                     "id" => "domaines_paniers",
-                     "label" => "Domaines",
-                     "categories" => [
-                                      ['id' => 1,
-                                       'label' => 'Coups de coeur',
-                                       'categories' => [],
-                                       'items' => [
-                                                   ['id' => 4,
-                                                    'label' => 'Mes coups de coeur - marcel doob',
-                                                    'options' => [
-                                                                  'ico' => BASE_URL.'/public/admin/images/picto/paniers_16.png']]
-                                       ],
-
-                                       'options' => ['ico' => BASE_URL.'/public/admin/images/picto/domaines_16.png',
-                                                                 'removeCheckbox' => true]
-                                      ]
-                     ],
-                     "items" => [],
-                     "options" => ["ico" => BASE_URL."/public/admin/images/picto/domaines_16.png",
-                                   "multipleSelection" => false]]]),
-      $this->_response->getBody());
+    $this->dispatch('abonne/get-paniers.json');
+
+    $this->assertJsonStringEqualsJsonString($this->_response->getBody(),
+                                            json_encode([
+                                                         ["id" => "panier_for_user",
+                                                          "label" => "Mes paniers",
+                                                          "categories" => [],
+                                                          "items" => [
+                                                                      ["id" => 2,
+                                                                       "label" => "Mes BD",
+                                                                       "options" => ["ico" => BASE_URL."/public/admin/images/picto/paniers_16.png"]]],
+                                                          "options" => ["multipleSelection" => false]],
+
+                                                         [
+                                                          "id" => "domaines_paniers",
+                                                          "label" => "Domaines",
+                                                          "categories" => [
+                                                                           ['id' => 1,
+                                                                            'label' => 'Coups de coeur',
+                                                                            'categories' => [],
+                                                                            'items' => [
+                                                                                        ['id' => 4,
+                                                                                         'label' => 'Mes coups de coeur - marcel doob',
+                                                                                         'options' => [
+                                                                                                       'ico' => BASE_URL.'/public/admin/images/picto/paniers_16.png']]
+                                                                            ],
+
+                                                                            'options' => ['ico' => BASE_URL.'/public/admin/images/picto/domaines_16.png',
+                                                                                          'removeCheckbox' => true]
+                                                                           ]
+                                                          ],
+                                                          "items" => [],
+                                                          "options" => ["ico" => BASE_URL."/public/admin/images/picto/domaines_16.png",
+                                                                        "multipleSelection" => false]]]),
+                                            $this->_response->getBody());
   }
 
 
   /** @test **/
-  public function getPaniersAsInviteShouldReturnMarcusPanierWithoutDomainesAsJSON() {
+  public function getPaniersAsInviteShouldReturnMarcusPanierWithoutDomainesAsJSON()
+  {
     $this->marcus->beInvite();
 
-    $this->dispatch('abonne/get-paniers.json',true);
-
-    $this->assertJsonStringEqualsJsonString(
-      $this->_response->getBody(),
-      json_encode([
-                    ["id" => "panier_for_user",
-                     "label" => "Mes paniers",
-                     "categories" => [],
-                     "items" => [
-                       ["id" => 2,
-                        "label" => "Mes BD",
-                        "options" => ["ico" => BASE_URL."/public/admin/images/picto/paniers_16.png"]]],
-                     "options" => ["multipleSelection" => false]]
-                    ]),
-      $this->_response->getBody());
+    $this->dispatch('abonne/get-paniers.json');
+
+    $this->assertJsonStringEqualsJsonString($this->_response->getBody(),
+                                            json_encode([
+                                                         ["id" => "panier_for_user",
+                                                          "label" => "Mes paniers",
+                                                          "categories" => [],
+                                                          "items" => [
+                                                                      ["id" => 2,
+                                                                       "label" => "Mes BD",
+                                                                       "options" => ["ico" => BASE_URL."/public/admin/images/picto/paniers_16.png"]]],
+                                                          "options" => ["multipleSelection" => false]]
+                                                         ]),
+                                            $this->_response->getBody());
+  }
+}
+
+
+
+
+abstract class AbstractAbonneControllerPaniersDeleteTestCase extends AbstractControllerTestCase
+{
+
+  public function setup()
+  {
+    parent::setup();
+
+    $marcel = $this->fixture(Class_Users::class,
+                             ['id' => 47,
+                              'login' => 'marcel',
+                              'password' => 'secret',
+                              'prenom' => 'marcel',
+                              'nom' => 'doob']);
+    $marcel->beAdminPortail()->assertSave();
+
+    $cards = $this->fixture(Class_PanierNotice::class,
+                            ['id' => 4,
+                             'id_panier' => 2,
+                             'libelle' => 'Mes coups de coeur',
+                             'date_maj' => '10/02/2011',
+                             'notices' => 'POMMEDAPI/Class_Album@1',
+                             'user' => $marcel]);
+
+    $this->fixture(Class_Catalogue::class,
+                   ['id' => 1,
+                    'libelle' => 'Coups de coeur',
+                    'panier_notices' => [$cards]]);
+
+    $this->_fixtureAlbum();
+
+    $item = $this->fixture(Class_Exemplaire::class,
+                           ['id' => 1,
+                            'notice_id' => 1,
+                            'id_origine' => 1]);
+
+    $this->fixture(Class_Notice::class,
+                   ['id' => 1,
+                    'type_doc' => 'ArteVod',
+                    'clef_alpha' => 'POMMEDAPI',
+                    'exemplaires' => [$item]]);
+
+    ZendAfi_Auth::getInstance()->logUser($marcel);
+
+    $this->dispatch('/abonne/supprimer-de-la-selection/id_profil/1/selection_id/4/record_id/1/delete/1');
+    Class_PanierNotice::clearCache();
+  }
+
+
+  protected function _fixtureAlbum() : self {
+    return $this;
+  }
+}
+
+
+
+
+class AbonneControllerPaniersDeleteWithExistsAlbumTest
+  extends AbstractAbonneControllerPaniersDeleteTestCase
+{
+
+  protected function _fixtureAlbum() : self {
+    $this->fixture(Class_Album::class,
+                   ['id' => 1,
+                    'titre' => 'Album title',
+                    'notice_id' => 1]);
+
+    return $this;
+  }
+
+
+  /** @test */
+  public function recordsKeysShouldHaveBeenErased()
+  {
+    $this->assertEquals([], Class_PanierNotice::find(4)->getClesNotices());
+  }
+}
+
+
+
+
+class AbonneControllerPaniersDeleteWithExistsAlbumOnIdOrigineTest
+  extends AbstractAbonneControllerPaniersDeleteTestCase
+{
+
+  protected function _fixtureAlbum() : self {
+    $this->fixture(Class_Album::class,
+                   ['id' => 2,
+                    'titre' => 'Album title',
+                    'notice_id' => 1,
+                    'id_origine' => 1]);
+
+    return $this;
   }
 
 
+  /** @test */
+  public function recordsKeysShouldHaveBeenErased()
+  {
+    $this->assertEquals([], Class_PanierNotice::find(4)->getClesNotices());
+  }
 }
 
-?>
\ No newline at end of file
+
+
+
+class AbonneControllerPaniersDeleteWithoutAlbumTest
+  extends AbstractAbonneControllerPaniersDeleteTestCase
+{
+
+  /** @test */
+  public function recordsKeysShouldHaveBeenErased()
+  {
+    $this->assertEquals([], Class_PanierNotice::find(4)->getClesNotices());
+  }
+}