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 couponPlaceOrderData
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; // ?AddressAdresy 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 ordersPrejavte 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 kryptomienOdoslaní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.