smart-dato / brt-documento-di-ritiro
Generate BRT (Bartolini) Documento di Ritiro pickup documents and segnacollo parcel labels
Package info
github.com/smart-dato/brt-documento-di-ritiro
pkg:composer/smart-dato/brt-documento-di-ritiro
Fund package maintenance!
Requires
- php: ^8.4
- ext-gd: *
- barryvdh/laravel-dompdf: ^3.0
- illuminate/contracts: ^11.0||^12.0||^13.0
- intervention/image: ^2.3
- laminas/laminas-barcode: ^2.14
- setasign/fpdf: ^1.8
- setasign/fpdi: ^2.3
- spatie/laravel-data: ^4.7
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^11.0.0||^10.0.0||^9.0.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- spatie/laravel-ray: ^1.35
README
Generate BRT (Bartolini) "Documento di Ritiro" pickup paperwork from plain PHP data objects:
- the A4 corriere document ("DA CONSEGNARE AL CORRIERE") — one page per delivery-address group, with segnacollo thumbnails, weights, volumes and cash-on-delivery totals,
- one A4 parcel label per parcel ("DA APPLICARE SUL PACCO"), each carrying its segnacollo barcode and the shipment barcode strip,
- segnacollo barcode allocation from BRT number ranges, with database locking against duplicate numbers,
- the fixed-width FNVAO booking record BRT's VAS system parses.
Everything is rendered in memory and returned as binaries — the package never touches your models, storage paths or database rows (except the barcode-range table it owns). Optional helpers store the results on any Laravel filesystem disk.
Requirements
- PHP 8.4+ with the GD extension
- Laravel 11, 12 or 13
Installation
composer require smart-dato/brt-documento-di-ritiro
Publish the config file if you need to override defaults:
php artisan vendor:publish --tag="brt-documento-di-ritiro-config"
The segnacollo allocator persists its number ranges in a table (default brt_documento_di_ritiro). Publish and run the migration unless the table already exists in your schema:
php artisan vendor:publish --tag="brt-documento-di-ritiro-migrations"
php artisan migrate
Usage
Generating a documento di ritiro
Describe the pickup with data objects and let the fluent builder render everything:
use SmartDato\BrtDocumentoDiRitiro\Data\AddressData; use SmartDato\BrtDocumentoDiRitiro\Data\BrandingData; use SmartDato\BrtDocumentoDiRitiro\Data\ParcelData; use SmartDato\BrtDocumentoDiRitiro\Data\PickupData; use SmartDato\BrtDocumentoDiRitiro\Data\ShipmentData; use SmartDato\BrtDocumentoDiRitiro\Facades\BrtDocumentoDiRitiro; $result = BrtDocumentoDiRitiro::document() ->pickup(new PickupData( documentNumber: 'OLP202600044200', documentDate: '2026-08-24', )) ->sender(new AddressData( personName: 'Mario Balistreri', street: 'Via Venezia 22', zipcode: '94100', city: 'Enna', countryCode: 'it', countryName: 'Italy', phone: '3476221921', )) ->branding(new BrandingData( termsUrl: 'www.example.com', sideLogoPath: '/path/to/your/side-logo.png', )) ->clientCode('0123456') ->addShipment(new ShipmentData( key: 'SHIP0001', deliveryAddress: new AddressData(/* ... */), onBehalfOf: 'Your Company', declaredParcelCount: 2, parcels: [ new ParcelData(key: 'SHIP0001X1', weight: 10.0, volume: 0.04), new ParcelData(key: 'SHIP0001X2', weight: 10.0, volume: 0.07), ], useBarcodeSideLayout: true, )) ->generate();
branding() and clientCode() are required: the BRT client code, terms URL, side logo and non-IT fallback recipient are your business data — the package ships none of it.
The GenerationResult carries every artifact and the barcode bookkeeping:
$result->documentPdf(); // corriere pages + all parcel labels, merged $result->corrierePdf(); // corriere pages only $result->parcelLabels(); // parcel key => label PDF (newly rendered labels) $result->barcodes(); // parcel key => segnacollo barcode (all parcels) $result->allocatedBarcodes(); // parcel key => BarcodeAllocation (newly allocated only) $result->labeledParcelKeys(); // parcels that received a label in this run
Store the artifacts on any Laravel disk — the helpers throw a StorageException when a write fails:
$result->storeCorrierePdf('pickups/corriere.pdf') ->storeDocumentPdf('pickups/document.pdf') ->storeDocumentPdf('pickups/document.pdf', disk: 's3') ->storeParcelLabels(fn (string $parcelKey) => "labels/{$parcelKey}.pdf");
Parcels that already carry a barcode keep it (existingBarcode), and parcels that already have a label are skipped but stay part of the merged document (hasLabel + existingLabelPdf).
Segnacollo barcode allocation
Barcodes are drawn from number ranges BRT assigns to you. Seed them once:
use SmartDato\BrtDocumentoDiRitiro\Models\SegnacolloRange; SegnacolloRange::create([ 'from' => '10000000000010', 'to' => '10000001000002', 'next' => null, ]);
The database allocator hands out sequential numbers with the BRT check digit inside a locking transaction, rolls over between ranges and returns null on exhaustion (the generator then falls back to the parcel key). Monitor the remaining stock:
use SmartDato\BrtDocumentoDiRitiro\Contracts\SegnacolloAllocator; app(SegnacolloAllocator::class)->available();
Bind your own SegnacolloAllocator implementation to replace the database-backed default.
FNVAO booking record
Render the fixed-width booking file BRT expects when a pickup is announced:
use SmartDato\BrtDocumentoDiRitiro\Data\BookingData; use SmartDato\BrtDocumentoDiRitiro\Facades\BrtDocumentoDiRitiro; $file = BrtDocumentoDiRitiro::bookingFile(new BookingData( reference: 'OLP202600044200', referenceLength: 15, clientCode: '0123456', exportedAt: '2026-08-21 14:30:15', pickupAfter: '2026-08-24 09:30:00', sender: new AddressData(/* ... incl. province */), senderStreetLines: ['Via Venezia 22'], weight: 21.5, volume: 0.113, parcelCount: 2, consignee: null, // hub or direct-delivery consignee block, blank when null )); $file->content; // the FNVAO record (ASCII, fixed-width) $file->filename; // fnvao_20260821_143015#####.txt
Configuration
return [ 'max_parcels' => 20, // BRT's per-document parcel cap 'allocator' => [ 'connection' => null, // connection for the range table 'table' => 'brt_documento_di_ritiro', ], 'fallback_delivery_address' => [...], // printed for non-IT destinations 'fonts' => [...], // per-font file overrides (null = bundled) 'images' => [...], // BRT logo/background overrides (null = bundled) ];
A note on the bundled fonts
The rendered form uses Verdana and Franklin Gothic, which are proprietary typefaces. The bundled copies exist so the output matches the documents BRT has historically accepted — make sure your own licensing situation covers their use, or point the fonts config entries at typefaces you are licensed for.
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Credits
License
The MIT License (MIT). Please see License File for more information.