Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Lamoda B2B Platform.dto Laravel Package

lamoda/lamoda-b2b-platform.dto

A collection of data transfer objects for the Lamoda B2B platform, offering typed, structured value objects for orders, products, and API payloads. Keeps business data consistent and validated across services with a lightweight, framework-agnostic PHP implementation.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and boot

composer require <vendor>/<package>
php artisan vendor:publish --provider="<Vendor>\<Package>\<Package>ServiceProvider"
php artisan migrate

Publish tags individually if you only need part of the surface — --tag=config, --tag=migrations, --tag=views. Publishing everything on a first pass dumps migrations you may not want to own.

Where to look first

  1. config/<package>.php — the connective tissue. Read every key before writing code; most "why isn't this working" tickets resolve here.
  2. The service provider's register()/boot() — shows what is bound in the container, which interfaces you can swap, and which events are listened to.
  3. src/Models/ — the package ships Eloquent models (InboundShipment and friends). Treat these as the primary API; the repository/service classes are usually thin wrappers over them.
  4. database/migrations/ — the schema is the real documentation for relationships and nullability.

First use case

Create an inbound shipment with its document number, then read it back:

use <Vendor>\<Package>\Models\InboundShipment;

$shipment = InboundShipment::create([
    'reference'       => 'INB-2024-0001',
    'document_number' => 'DOC-99812',   // added in 1.7.0
    'warehouse_id'    => $warehouse->id,
]);

$shipment->document_number; // 'DOC-99812'

If that round-trips, the install is sound and you can move on to the shipping/line-item workflows.

Implementation Patterns

Resolve through the container, not new

Bind-dependent classes should be injected or resolved via the facade so config and test overrides apply:

public function __construct(private InboundShipmentService $shipments) {}

Type-hint the package's interface, not the concrete class, if one exists — that is the seam the package expects you to use for swapping behaviour.

Wrap multi-model writes in transactions

Inbound shipments almost always touch line items, stock movements and status history. The package does not open a transaction for you:

DB::transaction(function () use ($payload) {
    $shipment = InboundShipment::create($payload);
    $shipment->lines()->createMany($payload['lines']);
});

Set the document number at creation time, not after

Adding a field in a minor release usually means a nullable column. Prefer populating it in the same create()/update() call as the rest of the payload so validation, events, and any observers see the final state exactly once. Avoid a create-then-patch pattern — it fires model events twice and can trip uniqueness checks against a half-built record.

Validate upstream with Form Requests

The package validates at the model/database layer only (types and constraints). Put business rules — document number format, uniqueness scoped to a supplier or fiscal year — in a FormRequest or a dedicated Rule object so failures surface as 422s rather than QueryExceptions.

Lean on the event system for side effects

Anything downstream — notifying a warehouse, pushing to an ERP, generating PDFs — belongs in a listener on the package's shipment events, not inline in your controller. This keeps the package upgradeable and lets you queue the work:

Event::listen(ShipmentConfirmed::class, SyncToErp::class);

Implement ShouldQueue on the listener and make it idempotent — events can be retried.

Testing

Use the shipped factories with RefreshDatabase, and Http::fake()/Queue::fake() for outbound calls. Assert on the model state (assertDatabaseHas) rather than on internal service method calls, otherwise a patch release that refactors internals breaks your suite for no reason.

Feature-flag the new field if you roll out gradually

Because 1.7.0 is additive, you can deploy the schema and start populating document_number for new shipments while backfilling historical rows in a queued job. Gate reads with $shipment->document_number ?? $shipment->reference during the transition.

Gotchas and Tips

Nullable does not mean optional

The new document_number column will be nullable for backwards compatibility, so nothing fails if you forget it. If your business requires it, enforce that in validation — the database will happily accept null.

Existing rows and backfill

Migrations run but existing shipments get null. Write a chunked backfill (->chunkById(500, ...)) rather than a single UPDATE, and keep it idempotent so a re-run is harmless. Do not put data transformation in the migration itself.

Uniqueness needs an index decision

If document numbers must be unique, add a unique index in a separate migration after the backfill completes. Adding it in the same migration as the column will fail on any environment with duplicate or null rows depending on your DB driver's null semantics (MySQL and Postgres both allow multiple NULLs).

Mass assignment

Check $fillable/$guarded on the package model. New columns are sometimes not added to $fillable in the same release. If create(['document_number' => ...]) silently drops the value, that is the cause — set it explicitly or extend the model.

Config caching

php artisan config:cache in deploy scripts will freeze the package config. If behaviour differs between local and production, clear and re-cache before you start debugging application code.

N+1 on shipment listings

Shipment index screens are the classic N+1 trap. Eager load relationships explicitly:

InboundShipment::with(['lines', 'warehouse'])->paginate(50);

Enable Model::preventLazyLoading() outside production to catch these early.

Events inside transactions

Listeners registered with ShouldHandleEventsAfterCommit (or dispatched after commit) avoid notifying downstream systems about shipments that then roll back. Verify the package's events are dispatched at the right point before wiring up external integrations.

Extension points worth knowing

  • Container bindings in the service provider — override an interface to customise behaviour without forking.
  • Model observers — attach in your own AppServiceProvider rather than editing package code.
  • Config keys for table names — useful when embedding into an existing schema.

Debugging

DB::listen() plus Telescope will show you the exact queries the package issues; almost every performance complaint is visible there. Wrap suspicious calls in DB::enableQueryLog() when Telescope isn't available. For state machines and status transitions, log every transition in an observer — silent no-op updates are the most common "the package ignored my change" report.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route