NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky
Shops for Laravel

Vytvorenie objednávky

Shops::cart($cart)->checkout() vytvorí z košíka objednávku v jednej transakcii (PlaceOrderAction). Nedostatok tovaru vráti všetko späť a košík nechá nedotknutý:

use RoundlyConsulting\Shops\Facades\Shops;
use RoundlyConsulting\Shops\Orders\DataTransferObjects\Address;
use RoundlyConsulting\Shops\Orders\DataTransferObjects\PlaceOrderData;

$address = new Address(
    name: 'Jane Doe',
    street: 'Main Street 1',
    city: 'Berlin',
    postalCode: '10115',
    countryIso: 'DE',
    email: '[email protected]',
);

$order = Shops::cart($cart)->checkout(new PlaceOrderData(
    billing: $address,
    shipping: $address,          // the shipping country drives per-country tax
    couponCode: 'WELCOME10',     // optional — defaults to the cart's coupon_code
    note: 'Leave at the door',   // optional
    customer: $user,             // optional — defaults to the cart owner
));

$order = Shops::cart($cart)->checkout();   // no addresses, the cart's own coupon_code

// The same as an action:
$order = app(\RoundlyConsulting\Shops\Actions\Orders\PlaceOrderAction::class)->execute($cart, $data);

Čo sa stane

  • 1. Riadok košíka sa zamkne na celý čas vytvárania objednávky. Prázdny košík alebo riadok, ktorého variant bol od pridania zmazaný či soft-deletnutý, sa odmietne výnimkou CheckoutRefusedException skôr, než sa čokoľvek zapíše.
  • 2. Vytvorí sa Order so stavom New, menou košíka, adresami a poznámkou.
  • 3. Priradí sa kupujúci — zadaný zákazník, inak vlastník košíka (objednávky hostí ho nemajú) — a skopíruje sa shop_id košíka; položky objednávky zdedia jej obchod.
  • 4. Každý riadok košíka sa skopíruje cez internú AddOrderItemAction s názvom, sku, cenou a daňovou triedou, ktoré si zafixoval košík — teda tak, ako ich videl zákazník, aj keď sa katalóg medzitým preceňoval — spolu so sadzbou dane.
  • 5. Zarezervuje sa tovar — nedostatok vyhodí InsufficientStockException a všetko sa vráti späť.
  • 6. Kupón (zadaný kód, inak coupon_code košíka) sa uplatní a jeho zľava sa zafixuje. Neexistujúci alebo neuplatniteľný kód sa ticho preskočí a nákup nikdy nezablokuje.
  • 7. Vypočíta sa cena dopravy a zafixuje sa do objednávky (pozrite Doprava nižšie).
  • 8. Košík sa vyprázdni, objednávka sa obnoví a vráti; OrderPlaced sa spustí po potvrdení transakcie.

Odmietnuté objednávky

Keďže košík zostáva zamknutý, dvakrát odoslané „Objednať“ vytvorí jednu objednávku: druhý request počká, nájde košík vyprázdnený a odmietne sa výnimkou Orders\Exceptions\CheckoutRefusedException — zachyťte ju a zobrazte objednávku, ktorú vytvoril prvý request. Rovnaká výnimka odmietne prázdny košík aj riadok, ktorého variant už neexistuje, a v $cartItem tento riadok uvedie:

use RoundlyConsulting\Shops\Facades\Shops;
use RoundlyConsulting\Shops\Orders\Exceptions\CheckoutRefusedException;

try {
    $order = Shops::cart($cart)->checkout($data);
} catch (CheckoutRefusedException $e) {
    $e->cartItem;   // ?CartItem — the line whose variant was removed; null for an empty cart
    // A double-submitted "Place order" lands here too: show the order the first request placed.
}

Doprava

Pri doručovacej adrese si objednávka vypýta cenu od naviazaného ShippingMethod (shops.shipping.method) — až po pridaní riadkov, aby ich metóda mohla oceniť — a výsledok zafixuje do objednávky ako shipping_cost v mene objednávky. Možnosť, ktorú si zvolil zákazník, odovzdajte namiesto toho cez shippingCost. Konečná cena objednávky aj platba ju zahŕňajú a kupón na dopravu zdarma ju odpočíta. Bez adresy a bez zvolenej ceny sa doprava neúčtuje; košík nemá cieľ, preto Shops::cart($cart)->price() dopravu nikdy nezahŕňa:

use RoundlyConsulting\Money\Money;
use RoundlyConsulting\Shops\Facades\Shops;
use RoundlyConsulting\Shops\Orders\DataTransferObjects\PlaceOrderData;

// Quoted through shops.shipping.method and snapshotted onto the order:
$order = Shops::cart($cart)->checkout(new PlaceOrderData(shipping: $address));

// Or the option the customer chose:
$order = Shops::cart($cart)->checkout(new PlaceOrderData(
    shipping: $address,
    shippingCost: Money::ofMinor(490, 'EUR'),
));

$order->shipping_cost;           // ?Money, in the order currency
$order->price->shippingCost();   // the shipping charged — zero with a free-shipping coupon

PlaceOrderData

Všetky polia sú voliteľné:

new PlaceOrderData(
    ?Address $billing = null,
    ?Address $shipping = null,
    ?string $couponCode = null,
    ?string $note = null,
    ?Model $customer = null,
    ?Money $shippingCost = null,   // the shipping option the customer chose — else quoted
);

Ručne zakladané objednávky

Aj objednávku z administrácie či telefonickú objednávku založte cez košík — zafixovanie riadkov, rezervácia tovaru a uplatnenie kupónu tak prebehnú spolu:

use RoundlyConsulting\Shops\Cart\Cart;
use RoundlyConsulting\Shops\Facades\Shops;
use RoundlyConsulting\Shops\Orders\DataTransferObjects\PlaceOrderData;

// An admin or phone order: go through a cart so the snapshot,
// the reservation and the coupon redemption run together.
$cart = Cart::create(['currency' => 'EUR', 'shop_id' => $shop->id]);
Shops::cart($cart)->add($variant, 2);
$order = Shops::cart($cart)->checkout(new PlaceOrderData(customer: $customer));

Adresy

Fakturačná a doručovacia adresa sa ukladajú ako JSON a castujú na nemenné DTO Address s poľami name, street, city, postalCode, countryIso a voliteľnými company, phone a email:

use RoundlyConsulting\Shops\Orders\DataTransferObjects\Address;

$order->shipping_address;               // ?Address — an immutable DTO (JSON column)
$order->shipping_address?->countryIso;  // "DE"

$address = Address::fromArray([
    'name' => 'Jane Doe', 'street' => 'Main Street 1', 'city' => 'Berlin',
    'postal_code' => '10115', 'country_iso' => 'DE', 'phone' => '+49 30 000000',
]);
$address->toArray();                    // snake_case keys

// Reuse the cast on your own models:
protected function casts(): array
{
    return ['delivery_address' => \RoundlyConsulting\Shops\Support\Casts\AddressCast::class];
}

Z adresára zákazníka

S balíkom addresses-for-laravel poskladáte adresy objednávky z uložených adries zákazníka. Doručovacia sa berie z primárnej doručovacej adresy, fakturačná z primárnej fakturačnej; ak fakturačná chýba, použije sa doručovacia (prepína sa cez shops.addresses.billing_same_as_shipping alebo argument billingSameAsShipping). Shops::addresses() vráti AddressBook, ktorý to zabezpečuje. Model zákazníka musí implementovať Addressable:

use Illuminate\Foundation\Auth\User as Authenticatable;
use RoundlyConsulting\Addresses\Contracts\Addressable;
use RoundlyConsulting\Addresses\Traits\HasAddresses;

class User extends Authenticatable implements Addressable
{
    use HasAddresses;
}

$order = Shops::cart($cart)->checkout(PlaceOrderData::fromAddressBook($user, couponCode: 'WELCOME10'));

// Or read the defaults yourself:
$defaults = Shops::addresses()->defaults($user);   // OrderAddresses
$defaults->shipping;                               // ?Address
$defaults->billing;                                // ?Address

Adresy sa do objednávky zafixujú — na adresár nevedie žiadny cudzí kľúč, takže úprava uloženej adresy nikdy nezmení staršiu objednávku.

Zákazník objednávky

Objednávka má voliteľného polymorfného zákazníka. Využíva ho adresár, kredit v obchode aj recenzie s overeným nákupom; môže byť null, takže objednávky hostí sú plne podporované:

$order->customer;        // ?Model — the buyer, copied from the cart owner at place-order
$order->hasCustomer();   // false for guest orders

Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

Ďalšie spôsoby podpory vrátane kryptomien

Odoslaním daru súhlasíte s našimi podmienkami prijímania darov.

Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.