Просмотр исходного кода

Stop a shared phone number merging two customers in an import (#530)

* Stop a shared phone number merging two customers in an import

* Keep a same-name row with another customer number from matching by name
Bernt Christian Egeland 1 день назад
Родитель
Сommit
4ebb19cc88
2 измененных файлов с 39 добавлено и 3 удалено
  1. 25 0
      src/__tests__/features/import/pipeline.test.ts
  2. 14 3
      src/features/import/Lib/pipeline.ts

+ 25 - 0
src/__tests__/features/import/pipeline.test.ts

@@ -106,6 +106,31 @@ describe('import plan', () => {
     ])
   })
 
+  it('does not take a shared phone for the same customer when the email or number differs', () => {
+    // Anna's household: her partner has the same landline but an email and a
+    // customer number of his own. Matching on the phone renamed Anna into him.
+    const rows = [
+      ['Erik Berg', 'erik@example.com', '91234567', ''],
+      ['Erik Berg', '', '91234567', '2001'],
+      // Same name and phone, but a customer number of someone else: not Anna either.
+      ['Anna Berg', '', '91234567', '2001'],
+      ['Anna Berg', 'anna@example.com', '91234567', '1001'],
+    ]
+    const plan = planImport(
+      rows,
+      {
+        '0': 'customer.name',
+        '1': 'customer.email',
+        '2': 'customer.phone',
+        '3': 'customer.customerNumber',
+      },
+      options('customers'),
+      existing
+    )
+    expect(plan.rows.map((r) => r.action)).toEqual(['create', 'create', 'create', 'update'])
+    expect(plan.rows[3].customerMatch).toMatchObject({ id: 'c1' })
+  })
+
   it('applies the duplicate rule and per-row overrides', () => {
     const rows = [
       ['Anna Berg', 'anna@example.com'],

+ 14 - 3
src/features/import/Lib/pipeline.ts

@@ -483,8 +483,17 @@ class ExistingIndex {
       if (m) return m
     }
     if (k.phone) {
-      const m = hit(this.byPhone.get(k.phone), 'phone')
-      if (m) return m
+      const found = this.byPhone.get(k.phone)
+      // A phone is often shared: a household's landline, a company's switchboard.
+      // It is only the same customer when the row's email and customer number do
+      // not say it is someone else; otherwise the update would rename one person
+      // into another.
+      if (found) {
+        const emailClash = k.email && found.email && found.email.toLowerCase() !== k.email
+        const numberClash =
+          k.number && found.customerNumber && found.customerNumber.toLowerCase() !== k.number
+        if (!emailClash && !numberClash) return hit(found, 'phone')
+      }
     }
     if (k.name) {
       const found = this.byName.get(k.name)
@@ -492,7 +501,9 @@ class ExistingIndex {
       if (found) {
         const emailClash = k.email && found.email && found.email.toLowerCase() !== k.email
         const phoneClash = k.phone && found.phone && phoneKey(found.phone) !== k.phone
-        if (!emailClash && !phoneClash) return hit(found, 'name')
+        const numberClash =
+          k.number && found.customerNumber && found.customerNumber.toLowerCase() !== k.number
+        if (!emailClash && !phoneClash && !numberClash) return hit(found, 'name')
       }
     }
     return undefined