Bugfix in parsing and logging parsing timestamp

This commit is contained in:
Marko Jovanovic 2025-10-14 18:08:51 +02:00
parent d7623a14f9
commit 8f1eb46f30
5 changed files with 123 additions and 17 deletions

View File

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20251014153643 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE contacts ADD parsed_filename VARCHAR(255) DEFAULT NULL');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SCHEMA public');
$this->addSql('ALTER TABLE contacts DROP parsed_filename');
}
}

View File

@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20251014154016 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE contacts ADD parsed_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
$this->addSql('COMMENT ON COLUMN contacts.parsed_at IS \'(DC2Type:datetime_immutable)\'');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SCHEMA public');
$this->addSql('ALTER TABLE contacts DROP parsed_at');
}
}

View File

@ -101,7 +101,10 @@ final class CleanMobileCommand extends Command
// Strip everything that is not a digit or '+' and then convert to the // Strip everything that is not a digit or '+' and then convert to the
// required "0049…" format (no leading '+') // required "0049…" format (no leading '+')
$normaliseTo0049 = static function(string $raw): string { $normaliseTo0049 = static function(?string $raw): ?string {
if (!$raw) {
return null;
}
$raw = preg_replace('/[^\d+]/', '', $raw); $raw = preg_replace('/[^\d+]/', '', $raw);
$raw = ltrim($raw, '+'); $raw = ltrim($raw, '+');
@ -119,7 +122,10 @@ final class CleanMobileCommand extends Command
}; };
// Very small, deterministic validation no external libs required // Very small, deterministic validation no external libs required
$isGermanMobile = static function(string $e164) use ($germanMobilePrefixes): bool { $isGermanMobile = static function(?string $e164) use ($germanMobilePrefixes): bool {
if (!$e164) {
return false;
}
// Must start with the German country code // Must start with the German country code
if (!str_starts_with($e164, '0049')) { if (!str_starts_with($e164, '0049')) {
return false; return false;
@ -149,10 +155,10 @@ final class CleanMobileCommand extends Command
$rowCount++; $rowCount++;
// 5.1 Get the raw number (first try HANDY_*, then generic VORWAHL/DURCHWAHL) // 5.1 Get the raw number (first try HANDY_*, then generic VORWAHL/DURCHWAHL)
$raw = $buildRawNumber($row, 'HANDY_VORWAHL', 'HANDY_DURCHWAHL') $raw1 = $buildRawNumber($row, 'HANDY_VORWAHL', 'HANDY_DURCHWAHL');
?? $buildRawNumber($row, 'VORWAHL', 'DURCHWAHL'); $raw2 = $buildRawNumber($row, 'VORWAHL', 'DURCHWAHL');
if ($raw === null) { if ($raw1 === null && $raw2 === null) {
// No number at all → empty column // No number at all → empty column
$row['HANDY_E164'] = ''; $row['HANDY_E164'] = '';
$csvWriter->insertOne($row); $csvWriter->insertOne($row);
@ -160,27 +166,35 @@ final class CleanMobileCommand extends Command
} }
// 5.2 Normalise to the canonical 0049… format // 5.2 Normalise to the canonical 0049… format
$e164 = $normaliseTo0049($raw); $e164_1 = $normaliseTo0049($raw1);
$e164_2 = $normaliseTo0049($raw2);
// 5.3 Validate // 5.3 Validate
if ($isGermanMobile($e164)) { if (!$isGermanMobile($e164_1) && !$isGermanMobile($e164_2)) {
// ----> VALID ------------------------------------------------- // ----> NOT VALID --------------------------------------------
$row['HANDY_E164'] = $e164; $row['HANDY_E164'] = '';
$csvWriter->insertOne($row); $invalid++;
} else if ($isGermanMobile($e164_1)) {
// ----> VALID 1 -------------------------------------------------
$row['HANDY_E164'] = $e164_1;
} else if ($isGermanMobile($e164_2)) {
// ----> VALID 2 -------------------------------------------------
$row['HANDY_E164'] = $e164_2;
}
if ($row['HANDY_E164']) {
// Create a Contact entity for DB insertion // Create a Contact entity for DB insertion
$contact = new Contacts(); $contact = new Contacts();
$contact->setPhoneNumber($e164); $contact->setPhoneNumber($row['HANDY_E164']);
$dueDate = (new \DateTime('tomorrow'))->setTime(16, 0, 0); $dueDate = (new \DateTime('tomorrow'))->setTime(16, 0, 0);
$contact->setDueDate($dueDate); $contact->setDueDate($dueDate);
$contact->setContacted(false); $contact->setContacted(false);
$contact->setParsedFilename($inputPath);
$contact->setParsedAt(new \DateTimeImmutable());
$validContacts[] = $contact; $validContacts[] = $contact;
} else {
// ----> NOT VALID --------------------------------------------
$row['HANDY_E164'] = '';
$csvWriter->insertOne($row);
$invalid++;
} }
$csvWriter->insertOne($row);
} }
// ------------------------------------------------------------- // -------------------------------------------------------------

View File

@ -28,6 +28,12 @@ class Contacts
#[ORM\Column(nullable: true)] #[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $contacted_at = null; private ?\DateTimeImmutable $contacted_at = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $parsed_filename = null;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $parsed_at = null;
public function getId(): ?int public function getId(): ?int
{ {
return $this->id; return $this->id;
@ -92,4 +98,24 @@ class Contacts
return $this; return $this;
} }
public function getParsedFilename(): ?string
{
return $this->parsed_filename;
}
public function setParsedFilename(?string $parsed_filename): void
{
$this->parsed_filename = $parsed_filename;
}
public function getParsedAt(): ?\DateTimeImmutable
{
return $this->parsed_at;
}
public function setParsedAt(?\DateTimeImmutable $parsed_at): void
{
$this->parsed_at = $parsed_at;
}
} }

View File

@ -1,4 +1,5 @@
PID;FALLNR;AUFNDAT;TAG;HANDY_VORWAHL;HANDY_DURCHWAHL;VORWAHL;DURCHWAHL PID;FALLNR;AUFNDAT;TAG;HANDY_VORWAHL;HANDY_DURCHWAHL;VORWAHL;DURCHWAHL
3762;3762;12.10.2025 09:33;12.10.2025 09:33;;;0228;28752181 3762;3762;12.10.2025 09:33;12.10.2025 09:33;;;0228;28752181
23521;23521;12.10.2025 17:22;12.10.2025 17:22;0176;72121270;; 23521;23521;12.10.2025 17:22;12.10.2025 17:22;0049()176;721-21-270;;
123123;123123;12.10.2025 22:54;12.10.2025 22:54;0160;;0176;72121270 123123;123123;12.10.2025 22:54;12.10.2025 22:54;0160;;0176;72121270
123123;123123;12.10.2025 22:54;12.10.2025 22:54;0160;;0176;

1 PID FALLNR AUFNDAT TAG HANDY_VORWAHL HANDY_DURCHWAHL VORWAHL DURCHWAHL
2 3762 3762 12.10.2025 09:33 12.10.2025 09:33 0228 28752181
3 23521 23521 12.10.2025 17:22 12.10.2025 17:22 0176 0049()176 72121270 721-21-270
4 123123 123123 12.10.2025 22:54 12.10.2025 22:54 0160 0176 72121270
5 123123 123123 12.10.2025 22:54 12.10.2025 22:54 0160 0176