[{"data":1,"prerenderedAt":3257},["ShallowReactive",2],{"navigation":3,"\u002Fapi\u002Fpromotions":72,"\u002Fapi\u002Fpromotions-surround":3252},[4,42,55],{"title":5,"path":6,"stem":7,"children":8,"page":41},"Api","\u002Fapi","api",[9,13,17,21,25,29,33,37],{"title":10,"path":11,"stem":12},"Cart API","\u002Fapi\u002Fcart","api\u002Fcart",{"title":14,"path":15,"stem":16},"Category API","\u002Fapi\u002Fcategory","api\u002Fcategory",{"title":18,"path":19,"stem":20},"Checkout API","\u002Fapi\u002Fcheckout","api\u002Fcheckout",{"title":22,"path":23,"stem":24},"Inventory","\u002Fapi\u002Finventory","api\u002Finventory",{"title":26,"path":27,"stem":28},"Order Numbers","\u002Fapi\u002Forder-numbers","api\u002Forder-numbers",{"title":30,"path":31,"stem":32},"Product API","\u002Fapi\u002Fproduct","api\u002Fproduct",{"title":34,"path":35,"stem":36},"Promotions API","\u002Fapi\u002Fpromotions","api\u002Fpromotions",{"title":38,"path":39,"stem":40},"Taxes","\u002Fapi\u002Ftaxes","api\u002Ftaxes",false,{"title":43,"path":44,"stem":45,"children":46,"page":41},"Getting Started","\u002Fgetting-started","getting-started",[47,51],{"title":48,"path":49,"stem":50},"Admin panel","\u002Fgetting-started\u002Fadmin-panel","getting-started\u002Fadmin-panel",{"title":52,"path":53,"stem":54},"Installation","\u002Fgetting-started\u002Finstallation","getting-started\u002Finstallation",{"title":56,"path":57,"stem":58,"children":59,"page":41},"Tasks","\u002Ftasks","tasks",[60,64,68],{"title":61,"path":62,"stem":63},"Building A Navigation","\u002Ftasks\u002Fbuilding-a-navigation","tasks\u002Fbuilding-a-navigation",{"title":65,"path":66,"stem":67},"Product Detail Page","\u002Ftasks\u002Fproduct-detail-page","tasks\u002Fproduct-detail-page",{"title":69,"path":70,"stem":71},"Product Listing Page","\u002Ftasks\u002Fproduct-listing-page","tasks\u002Fproduct-listing-page",{"id":73,"title":34,"body":74,"description":3246,"extension":3247,"links":3248,"meta":3249,"navigation":140,"path":35,"seo":3250,"stem":36,"__hash__":3251},"docs\u002Fapi\u002Fpromotions.md",{"type":75,"value":76,"toc":3233},"minimark",[77,81,94,101,106,113,492,495,499,502,605,608,612,622,955,961,964,1036,1039,1056,1337,1362,1369,1373,1378,1500,1507,1510,1584,1587,1591,1594,1773,1776,1931,1934,1937,1941,1944,2012,2015,2163,2166,2170,2177,2276,2283,2289,2353,2356,2360,2370,2547,2560,2564,2570,2673,2676,2749,2756,2763,2861,2864,2905,2908,2931,2934,2951,2954,3026,3036,3040,3052,3142,3152,3156,3159,3193,3204,3222,3229],[78,79,34],"h1",{"id":80},"promotions-api",[82,83,84,85,89,90,93],"p",{},"Promotions contain the rules that decide whether a cart receives a discount.\nA promotion returns a ",[86,87,88],"code",{},"DiscountResult"," when it applies and ",[86,91,92],{},"null"," when it does\nnot. Automatic promotions are evaluated whenever cart discounts or totals are\ncalculated and again during checkout. Code-based promotions are evaluated only\nafter their code has been attached to the cart.",[82,95,96,97,100],{},"Discount amounts are represented in minor currency units. A value of ",[86,98,99],{},"500","\ntherefore represents EUR 5.00 for a cart using euros.",[102,103,105],"h2",{"id":104},"defining-a-promotion","Defining a promotion",[82,107,108,109,112],{},"Implement the ",[86,110,111],{},"Promotion"," contract in your application. The context contains\nthe cart, its loaded items, currency, merchandise subtotal, selected shipping\noption, and the proportional discount allocator.",[114,115,120],"pre",{"className":116,"code":117,"language":118,"meta":119,"style":119},"language-php shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003C?php\n\nnamespace App\\Promotions;\n\nuse Larasell\\Larasell\\Contracts\\Promotions\\Promotion;\nuse Larasell\\Larasell\\Discounts\\DiscountResult;\nuse Larasell\\Larasell\\Discounts\\PromotionContext;\nuse Larasell\\Larasell\\Price;\n\nfinal class LargeOrderDiscount implements Promotion\n{\n    public function apply(PromotionContext $context): ?DiscountResult\n    {\n        if ($context->subtotal->amount() \u003C 10_000) {\n            return null;\n        }\n\n        return new DiscountResult(\n            identifier: 'large-order-discount',\n            name: 'Large order discount',\n            allocations: $context->fixedAmountOff(Price::of(1_000)),\n        );\n    }\n}\n","php","",[86,121,122,135,142,162,167,196,218,240,258,263,282,288,321,327,365,374,380,385,400,422,439,474,480,486],{"__ignoreMap":119},[123,124,127,131],"span",{"class":125,"line":126},"line",1,[123,128,130],{"class":129},"sMK4o","\u003C?",[123,132,134],{"class":133},"sTEyZ","php\n",[123,136,138],{"class":125,"line":137},2,[123,139,141],{"emptyLinePlaceholder":140},true,"\n",[123,143,145,149,153,156,159],{"class":125,"line":144},3,[123,146,148],{"class":147},"sbssI","namespace",[123,150,152],{"class":151},"sBMFI"," App",[123,154,155],{"class":129},"\\",[123,157,158],{"class":151},"Promotions",[123,160,161],{"class":129},";\n",[123,163,165],{"class":125,"line":164},4,[123,166,141],{"emptyLinePlaceholder":140},[123,168,170,173,176,178,181,183,186,188,190,192,194],{"class":125,"line":169},5,[123,171,172],{"class":147},"use",[123,174,175],{"class":133}," Larasell",[123,177,155],{"class":129},[123,179,180],{"class":133},"Larasell",[123,182,155],{"class":129},[123,184,185],{"class":133},"Contracts",[123,187,155],{"class":129},[123,189,158],{"class":133},[123,191,155],{"class":129},[123,193,111],{"class":133},[123,195,161],{"class":129},[123,197,199,201,203,205,207,209,212,214,216],{"class":125,"line":198},6,[123,200,172],{"class":147},[123,202,175],{"class":133},[123,204,155],{"class":129},[123,206,180],{"class":133},[123,208,155],{"class":129},[123,210,211],{"class":133},"Discounts",[123,213,155],{"class":129},[123,215,88],{"class":133},[123,217,161],{"class":129},[123,219,221,223,225,227,229,231,233,235,238],{"class":125,"line":220},7,[123,222,172],{"class":147},[123,224,175],{"class":133},[123,226,155],{"class":129},[123,228,180],{"class":133},[123,230,155],{"class":129},[123,232,211],{"class":133},[123,234,155],{"class":129},[123,236,237],{"class":133},"PromotionContext",[123,239,161],{"class":129},[123,241,243,245,247,249,251,253,256],{"class":125,"line":242},8,[123,244,172],{"class":147},[123,246,175],{"class":133},[123,248,155],{"class":129},[123,250,180],{"class":133},[123,252,155],{"class":129},[123,254,255],{"class":133},"Price",[123,257,161],{"class":129},[123,259,261],{"class":125,"line":260},9,[123,262,141],{"emptyLinePlaceholder":140},[123,264,266,270,273,276,279],{"class":125,"line":265},10,[123,267,269],{"class":268},"spNyl","final",[123,271,272],{"class":268}," class",[123,274,275],{"class":151}," LargeOrderDiscount",[123,277,278],{"class":268}," implements",[123,280,281],{"class":151}," Promotion\n",[123,283,285],{"class":125,"line":284},11,[123,286,287],{"class":129},"{\n",[123,289,291,294,297,301,304,306,309,312,315,318],{"class":125,"line":290},12,[123,292,293],{"class":268},"    public",[123,295,296],{"class":268}," function",[123,298,300],{"class":299},"s2Zo4"," apply",[123,302,303],{"class":129},"(",[123,305,237],{"class":151},[123,307,308],{"class":129}," $",[123,310,311],{"class":133},"context",[123,313,314],{"class":129},"):",[123,316,317],{"class":129}," ?",[123,319,320],{"class":151},"DiscountResult\n",[123,322,324],{"class":125,"line":323},13,[123,325,326],{"class":129},"    {\n",[123,328,330,334,337,339,342,345,347,350,353,356,359,362],{"class":125,"line":329},14,[123,331,333],{"class":332},"s7zQu","        if",[123,335,336],{"class":129}," ($",[123,338,311],{"class":133},[123,340,341],{"class":129},"->",[123,343,344],{"class":133},"subtotal",[123,346,341],{"class":129},[123,348,349],{"class":299},"amount",[123,351,352],{"class":129},"()",[123,354,355],{"class":129}," \u003C",[123,357,358],{"class":147}," 10_000",[123,360,361],{"class":129},")",[123,363,364],{"class":129}," {\n",[123,366,368,371],{"class":125,"line":367},15,[123,369,370],{"class":332},"            return",[123,372,373],{"class":129}," null;\n",[123,375,377],{"class":125,"line":376},16,[123,378,379],{"class":129},"        }\n",[123,381,383],{"class":125,"line":382},17,[123,384,141],{"emptyLinePlaceholder":140},[123,386,388,391,394,397],{"class":125,"line":387},18,[123,389,390],{"class":332},"        return",[123,392,393],{"class":147}," new",[123,395,396],{"class":151}," DiscountResult",[123,398,399],{"class":129},"(\n",[123,401,403,406,409,412,416,419],{"class":125,"line":402},19,[123,404,405],{"class":151},"            identifier",[123,407,408],{"class":129},":",[123,410,411],{"class":129}," '",[123,413,415],{"class":414},"sfazB","large-order-discount",[123,417,418],{"class":129},"'",[123,420,421],{"class":129},",\n",[123,423,425,428,430,432,435,437],{"class":125,"line":424},20,[123,426,427],{"class":151},"            name",[123,429,408],{"class":129},[123,431,411],{"class":129},[123,433,434],{"class":414},"Large order discount",[123,436,418],{"class":129},[123,438,421],{"class":129},[123,440,442,445,447,449,451,453,456,458,460,463,466,468,471],{"class":125,"line":441},21,[123,443,444],{"class":151},"            allocations",[123,446,408],{"class":129},[123,448,308],{"class":129},[123,450,311],{"class":133},[123,452,341],{"class":129},[123,454,455],{"class":299},"fixedAmountOff",[123,457,303],{"class":129},[123,459,255],{"class":151},[123,461,462],{"class":129},"::",[123,464,465],{"class":299},"of",[123,467,303],{"class":129},[123,469,470],{"class":147},"1_000",[123,472,473],{"class":129},")),\n",[123,475,477],{"class":125,"line":476},22,[123,478,479],{"class":129},"        );\n",[123,481,483],{"class":125,"line":482},23,[123,484,485],{"class":129},"    }\n",[123,487,489],{"class":125,"line":488},24,[123,490,491],{"class":129},"}\n",[82,493,494],{},"The identifier must be unique across all results returned for one calculation.\nUse a stable identifier because it is stored in the order snapshot. The name is\ncustomer-facing snapshot data and may be changed for future orders without\nrewriting existing orders.",[102,496,498],{"id":497},"registering-promotions","Registering promotions",[82,500,501],{},"Register promotion classes in an application service provider. The manager\nresolves each class through Laravel's container, so constructor dependencies\ncan be injected normally.",[114,503,505],{"className":116,"code":504,"language":118,"meta":119,"style":119},"use App\\Promotions\\LargeOrderDiscount;\nuse Larasell\\Larasell\\Discounts\\PromotionManager;\n\npublic function boot(PromotionManager $promotions): void\n{\n    $promotions->register(LargeOrderDiscount::class);\n}\n",[86,506,507,524,545,549,573,577,601],{"__ignoreMap":119},[123,508,509,511,513,515,517,519,522],{"class":125,"line":126},[123,510,172],{"class":147},[123,512,152],{"class":133},[123,514,155],{"class":129},[123,516,158],{"class":133},[123,518,155],{"class":129},[123,520,521],{"class":133},"LargeOrderDiscount",[123,523,161],{"class":129},[123,525,526,528,530,532,534,536,538,540,543],{"class":125,"line":137},[123,527,172],{"class":147},[123,529,175],{"class":133},[123,531,155],{"class":129},[123,533,180],{"class":133},[123,535,155],{"class":129},[123,537,211],{"class":133},[123,539,155],{"class":129},[123,541,542],{"class":133},"PromotionManager",[123,544,161],{"class":129},[123,546,547],{"class":125,"line":144},[123,548,141],{"emptyLinePlaceholder":140},[123,550,551,554,556,559,561,563,565,568,570],{"class":125,"line":164},[123,552,553],{"class":268},"public",[123,555,296],{"class":268},[123,557,558],{"class":299}," boot",[123,560,303],{"class":129},[123,562,542],{"class":151},[123,564,308],{"class":129},[123,566,567],{"class":133},"promotions",[123,569,314],{"class":129},[123,571,572],{"class":147}," void\n",[123,574,575],{"class":125,"line":169},[123,576,287],{"class":129},[123,578,579,582,584,586,589,591,593,595,598],{"class":125,"line":198},[123,580,581],{"class":129},"    $",[123,583,567],{"class":133},[123,585,341],{"class":129},[123,587,588],{"class":299},"register",[123,590,303],{"class":129},[123,592,521],{"class":151},[123,594,462],{"class":129},[123,596,597],{"class":147},"class",[123,599,600],{"class":129},");\n",[123,602,603],{"class":125,"line":220},[123,604,491],{"class":129},[82,606,607],{},"Registering the same class more than once has no effect.",[102,609,611],{"id":610},"user-entered-promotion-codes","User-entered promotion codes",[82,613,614,615,618,619,621],{},"Implement ",[86,616,617],{},"HasCode"," alongside ",[86,620,111],{}," when a customer must enter a code\nbefore the promotion runs. A coded promotion uses the same context, results,\nand allocation helpers as an automatic promotion.",[114,623,625],{"className":116,"code":624,"language":118,"meta":119,"style":119},"\u003C?php\n\nnamespace App\\Promotions;\n\nuse Larasell\\Larasell\\Contracts\\Promotions\\HasCode;\nuse Larasell\\Larasell\\Contracts\\Promotions\\Promotion;\nuse Larasell\\Larasell\\Discounts\\DiscountResult;\nuse Larasell\\Larasell\\Discounts\\PromotionContext;\n\nfinal class SaveTenPercent implements HasCode, Promotion\n{\n    public function code(): string\n    {\n        return 'SAVE10';\n    }\n\n    public function apply(PromotionContext $context): ?DiscountResult\n    {\n        if ($context->subtotal->amount() \u003C 5_000) {\n            return null;\n        }\n\n        return new DiscountResult(\n            identifier: 'save-ten-percent',\n            name: 'Save ten percent',\n            allocations: $context->percentageOff(10),\n        );\n    }\n}\n",[86,626,627,633,637,649,653,677,701,721,741,745,764,768,783,787,800,804,808,830,834,861,867,871,875,885,900,916,940,945,950],{"__ignoreMap":119},[123,628,629,631],{"class":125,"line":126},[123,630,130],{"class":129},[123,632,134],{"class":133},[123,634,635],{"class":125,"line":137},[123,636,141],{"emptyLinePlaceholder":140},[123,638,639,641,643,645,647],{"class":125,"line":144},[123,640,148],{"class":147},[123,642,152],{"class":151},[123,644,155],{"class":129},[123,646,158],{"class":151},[123,648,161],{"class":129},[123,650,651],{"class":125,"line":164},[123,652,141],{"emptyLinePlaceholder":140},[123,654,655,657,659,661,663,665,667,669,671,673,675],{"class":125,"line":169},[123,656,172],{"class":147},[123,658,175],{"class":133},[123,660,155],{"class":129},[123,662,180],{"class":133},[123,664,155],{"class":129},[123,666,185],{"class":133},[123,668,155],{"class":129},[123,670,158],{"class":133},[123,672,155],{"class":129},[123,674,617],{"class":133},[123,676,161],{"class":129},[123,678,679,681,683,685,687,689,691,693,695,697,699],{"class":125,"line":198},[123,680,172],{"class":147},[123,682,175],{"class":133},[123,684,155],{"class":129},[123,686,180],{"class":133},[123,688,155],{"class":129},[123,690,185],{"class":133},[123,692,155],{"class":129},[123,694,158],{"class":133},[123,696,155],{"class":129},[123,698,111],{"class":133},[123,700,161],{"class":129},[123,702,703,705,707,709,711,713,715,717,719],{"class":125,"line":220},[123,704,172],{"class":147},[123,706,175],{"class":133},[123,708,155],{"class":129},[123,710,180],{"class":133},[123,712,155],{"class":129},[123,714,211],{"class":133},[123,716,155],{"class":129},[123,718,88],{"class":133},[123,720,161],{"class":129},[123,722,723,725,727,729,731,733,735,737,739],{"class":125,"line":242},[123,724,172],{"class":147},[123,726,175],{"class":133},[123,728,155],{"class":129},[123,730,180],{"class":133},[123,732,155],{"class":129},[123,734,211],{"class":133},[123,736,155],{"class":129},[123,738,237],{"class":133},[123,740,161],{"class":129},[123,742,743],{"class":125,"line":260},[123,744,141],{"emptyLinePlaceholder":140},[123,746,747,749,751,754,756,759,762],{"class":125,"line":265},[123,748,269],{"class":268},[123,750,272],{"class":268},[123,752,753],{"class":151}," SaveTenPercent",[123,755,278],{"class":268},[123,757,758],{"class":151}," HasCode",[123,760,761],{"class":129},",",[123,763,281],{"class":151},[123,765,766],{"class":125,"line":284},[123,767,287],{"class":129},[123,769,770,772,774,777,780],{"class":125,"line":290},[123,771,293],{"class":268},[123,773,296],{"class":268},[123,775,776],{"class":299}," code",[123,778,779],{"class":129},"():",[123,781,782],{"class":147}," string\n",[123,784,785],{"class":125,"line":323},[123,786,326],{"class":129},[123,788,789,791,793,796,798],{"class":125,"line":329},[123,790,390],{"class":332},[123,792,411],{"class":129},[123,794,795],{"class":414},"SAVE10",[123,797,418],{"class":129},[123,799,161],{"class":129},[123,801,802],{"class":125,"line":367},[123,803,485],{"class":129},[123,805,806],{"class":125,"line":376},[123,807,141],{"emptyLinePlaceholder":140},[123,809,810,812,814,816,818,820,822,824,826,828],{"class":125,"line":382},[123,811,293],{"class":268},[123,813,296],{"class":268},[123,815,300],{"class":299},[123,817,303],{"class":129},[123,819,237],{"class":151},[123,821,308],{"class":129},[123,823,311],{"class":133},[123,825,314],{"class":129},[123,827,317],{"class":129},[123,829,320],{"class":151},[123,831,832],{"class":125,"line":387},[123,833,326],{"class":129},[123,835,836,838,840,842,844,846,848,850,852,854,857,859],{"class":125,"line":402},[123,837,333],{"class":332},[123,839,336],{"class":129},[123,841,311],{"class":133},[123,843,341],{"class":129},[123,845,344],{"class":133},[123,847,341],{"class":129},[123,849,349],{"class":299},[123,851,352],{"class":129},[123,853,355],{"class":129},[123,855,856],{"class":147}," 5_000",[123,858,361],{"class":129},[123,860,364],{"class":129},[123,862,863,865],{"class":125,"line":424},[123,864,370],{"class":332},[123,866,373],{"class":129},[123,868,869],{"class":125,"line":441},[123,870,379],{"class":129},[123,872,873],{"class":125,"line":476},[123,874,141],{"emptyLinePlaceholder":140},[123,876,877,879,881,883],{"class":125,"line":482},[123,878,390],{"class":332},[123,880,393],{"class":147},[123,882,396],{"class":151},[123,884,399],{"class":129},[123,886,887,889,891,893,896,898],{"class":125,"line":488},[123,888,405],{"class":151},[123,890,408],{"class":129},[123,892,411],{"class":129},[123,894,895],{"class":414},"save-ten-percent",[123,897,418],{"class":129},[123,899,421],{"class":129},[123,901,903,905,907,909,912,914],{"class":125,"line":902},25,[123,904,427],{"class":151},[123,906,408],{"class":129},[123,908,411],{"class":129},[123,910,911],{"class":414},"Save ten percent",[123,913,418],{"class":129},[123,915,421],{"class":129},[123,917,919,921,923,925,927,929,932,934,937],{"class":125,"line":918},26,[123,920,444],{"class":151},[123,922,408],{"class":129},[123,924,308],{"class":129},[123,926,311],{"class":133},[123,928,341],{"class":129},[123,930,931],{"class":299},"percentageOff",[123,933,303],{"class":129},[123,935,936],{"class":147},"10",[123,938,939],{"class":129},"),\n",[123,941,943],{"class":125,"line":942},27,[123,944,479],{"class":129},[123,946,948],{"class":125,"line":947},28,[123,949,485],{"class":129},[123,951,953],{"class":125,"line":952},29,[123,954,491],{"class":129},[82,956,957,958,960],{},"Register the class with ",[86,959,542],{}," in the same way as an automatic\npromotion. Registration makes the code available; it does not apply it to every\ncart.",[82,962,963],{},"Storefront code can attach, list, and remove codes through the cart:",[114,965,967],{"className":116,"code":966,"language":118,"meta":119,"style":119},"$cart->applyPromotionCode(' save10 ');\n$cart->promotionCodes(); \u002F\u002F ['SAVE10']\n\n$cart->removePromotionCode('SAVE10');\n",[86,968,969,993,1011,1015],{"__ignoreMap":119},[123,970,971,974,977,979,982,984,986,989,991],{"class":125,"line":126},[123,972,973],{"class":129},"$",[123,975,976],{"class":133},"cart",[123,978,341],{"class":129},[123,980,981],{"class":299},"applyPromotionCode",[123,983,303],{"class":129},[123,985,418],{"class":129},[123,987,988],{"class":414}," save10 ",[123,990,418],{"class":129},[123,992,600],{"class":129},[123,994,995,997,999,1001,1004,1007],{"class":125,"line":137},[123,996,973],{"class":129},[123,998,976],{"class":133},[123,1000,341],{"class":129},[123,1002,1003],{"class":299},"promotionCodes",[123,1005,1006],{"class":129},"();",[123,1008,1010],{"class":1009},"sHwdD"," \u002F\u002F ['SAVE10']\n",[123,1012,1013],{"class":125,"line":144},[123,1014,141],{"emptyLinePlaceholder":140},[123,1016,1017,1019,1021,1023,1026,1028,1030,1032,1034],{"class":125,"line":164},[123,1018,973],{"class":129},[123,1020,976],{"class":133},[123,1022,341],{"class":129},[123,1024,1025],{"class":299},"removePromotionCode",[123,1027,303],{"class":129},[123,1029,418],{"class":129},[123,1031,795],{"class":414},[123,1033,418],{"class":129},[123,1035,600],{"class":129},[82,1037,1038],{},"Codes are trimmed and converted to uppercase. Attaching the same normalized\ncode more than once has no effect. Code values must be non-empty and unique\nacross all registered coded promotions.",[82,1040,1041,1044,1045,1048,1049,1051,1052,1055],{},[86,1042,1043],{},"applyPromotionCode()"," throws a ",[86,1046,1047],{},"PromotionCodeException"," when the normalized\ncode is not registered, is outside its availability window, or its promotion\ndoes not currently return a positive discount. Storefront controllers should\nturn that exception into an error for the code input. Catch\n",[86,1050,1047],{}," rather than ",[86,1053,1054],{},"InvalidArgumentException"," so broken\npromotion implementations still surface as application errors.",[114,1057,1059],{"className":116,"code":1058,"language":118,"meta":119,"style":119},"use Illuminate\\Http\\Request;\nuse Larasell\\Larasell\\Exceptions\\Promotions\\PromotionCodeException;\nuse Larasell\\Larasell\\Models\\Cart;\n\npublic function store(Request $request, Cart $cart)\n{\n    $data = $request->validate(['code' => ['required', 'string']]);\n\n    try {\n        $cart->applyPromotionCode($data['code']);\n    } catch (PromotionCodeException $exception) {\n        return back()->withErrors(['code' => $exception->getMessage()]);\n    }\n\n    return back();\n}\n",[86,1060,1061,1080,1105,1127,1131,1161,1165,1218,1222,1229,1258,1280,1315,1319,1323,1333],{"__ignoreMap":119},[123,1062,1063,1065,1068,1070,1073,1075,1078],{"class":125,"line":126},[123,1064,172],{"class":147},[123,1066,1067],{"class":133}," Illuminate",[123,1069,155],{"class":129},[123,1071,1072],{"class":133},"Http",[123,1074,155],{"class":129},[123,1076,1077],{"class":133},"Request",[123,1079,161],{"class":129},[123,1081,1082,1084,1086,1088,1090,1092,1095,1097,1099,1101,1103],{"class":125,"line":137},[123,1083,172],{"class":147},[123,1085,175],{"class":133},[123,1087,155],{"class":129},[123,1089,180],{"class":133},[123,1091,155],{"class":129},[123,1093,1094],{"class":133},"Exceptions",[123,1096,155],{"class":129},[123,1098,158],{"class":133},[123,1100,155],{"class":129},[123,1102,1047],{"class":133},[123,1104,161],{"class":129},[123,1106,1107,1109,1111,1113,1115,1117,1120,1122,1125],{"class":125,"line":144},[123,1108,172],{"class":147},[123,1110,175],{"class":133},[123,1112,155],{"class":129},[123,1114,180],{"class":133},[123,1116,155],{"class":129},[123,1118,1119],{"class":133},"Models",[123,1121,155],{"class":129},[123,1123,1124],{"class":133},"Cart",[123,1126,161],{"class":129},[123,1128,1129],{"class":125,"line":164},[123,1130,141],{"emptyLinePlaceholder":140},[123,1132,1133,1135,1137,1140,1142,1144,1146,1149,1151,1154,1156,1158],{"class":125,"line":169},[123,1134,553],{"class":268},[123,1136,296],{"class":268},[123,1138,1139],{"class":299}," store",[123,1141,303],{"class":129},[123,1143,1077],{"class":151},[123,1145,308],{"class":129},[123,1147,1148],{"class":133},"request",[123,1150,761],{"class":129},[123,1152,1153],{"class":151}," Cart",[123,1155,308],{"class":129},[123,1157,976],{"class":133},[123,1159,1160],{"class":129},")\n",[123,1162,1163],{"class":125,"line":198},[123,1164,287],{"class":129},[123,1166,1167,1169,1172,1175,1177,1179,1181,1184,1187,1189,1191,1193,1196,1199,1201,1204,1206,1208,1210,1213,1215],{"class":125,"line":220},[123,1168,581],{"class":129},[123,1170,1171],{"class":133},"data ",[123,1173,1174],{"class":129},"=",[123,1176,308],{"class":129},[123,1178,1148],{"class":133},[123,1180,341],{"class":129},[123,1182,1183],{"class":299},"validate",[123,1185,1186],{"class":129},"([",[123,1188,418],{"class":129},[123,1190,86],{"class":414},[123,1192,418],{"class":129},[123,1194,1195],{"class":129}," =>",[123,1197,1198],{"class":129}," [",[123,1200,418],{"class":129},[123,1202,1203],{"class":414},"required",[123,1205,418],{"class":129},[123,1207,761],{"class":129},[123,1209,411],{"class":129},[123,1211,1212],{"class":414},"string",[123,1214,418],{"class":129},[123,1216,1217],{"class":129},"]]);\n",[123,1219,1220],{"class":125,"line":242},[123,1221,141],{"emptyLinePlaceholder":140},[123,1223,1224,1227],{"class":125,"line":260},[123,1225,1226],{"class":332},"    try",[123,1228,364],{"class":129},[123,1230,1231,1234,1236,1238,1240,1243,1246,1249,1251,1253,1255],{"class":125,"line":265},[123,1232,1233],{"class":129},"        $",[123,1235,976],{"class":133},[123,1237,341],{"class":129},[123,1239,981],{"class":299},[123,1241,1242],{"class":129},"($",[123,1244,1245],{"class":133},"data",[123,1247,1248],{"class":129},"[",[123,1250,418],{"class":129},[123,1252,86],{"class":414},[123,1254,418],{"class":129},[123,1256,1257],{"class":129},"]);\n",[123,1259,1260,1263,1266,1269,1271,1273,1276,1278],{"class":125,"line":284},[123,1261,1262],{"class":129},"    }",[123,1264,1265],{"class":332}," catch",[123,1267,1268],{"class":129}," (",[123,1270,1047],{"class":151},[123,1272,308],{"class":129},[123,1274,1275],{"class":133},"exception",[123,1277,361],{"class":129},[123,1279,364],{"class":129},[123,1281,1282,1284,1287,1290,1293,1295,1297,1299,1301,1303,1305,1307,1309,1312],{"class":125,"line":290},[123,1283,390],{"class":332},[123,1285,1286],{"class":299}," back",[123,1288,1289],{"class":129},"()->",[123,1291,1292],{"class":299},"withErrors",[123,1294,1186],{"class":129},[123,1296,418],{"class":129},[123,1298,86],{"class":414},[123,1300,418],{"class":129},[123,1302,1195],{"class":129},[123,1304,308],{"class":129},[123,1306,1275],{"class":133},[123,1308,341],{"class":129},[123,1310,1311],{"class":299},"getMessage",[123,1313,1314],{"class":129},"()]);\n",[123,1316,1317],{"class":125,"line":323},[123,1318,485],{"class":129},[123,1320,1321],{"class":125,"line":329},[123,1322,141],{"emptyLinePlaceholder":140},[123,1324,1325,1328,1330],{"class":125,"line":367},[123,1326,1327],{"class":332},"    return",[123,1329,1286],{"class":299},[123,1331,1332],{"class":129},"();\n",[123,1334,1335],{"class":125,"line":376},[123,1336,491],{"class":129},[82,1338,1339,1340,421,1343,1346,1347,1350,1351,1354,1355,1358,1359,1361],{},"The concrete types are ",[86,1341,1342],{},"UnknownPromotionCodeException",[86,1344,1345],{},"InapplicablePromotionCodeException",", and ",[86,1348,1349],{},"UnavailablePromotionCodeException",".\nEach exposes a stable ",[86,1352,1353],{},"reason()"," string and a ",[86,1356,1357],{},"context()"," array so storefronts\ncan map copy without parsing exception messages. Programmer errors such as\nduplicate identifiers or invalid allocation targets still throw\n",[86,1360,1054],{},".",[82,1363,1364,1365,1368],{},"An attached code is persisted on the cart, but its promotion is reevaluated\nwhenever discounts are calculated. If the customer changes the cart so that a\nminimum subtotal or another rule is no longer satisfied, the code remains\nattached but produces no discount. It starts applying again if the cart later\nsatisfies the rule. Use ",[86,1366,1367],{},"removePromotionCode()"," when the customer explicitly\nremoves it.",[102,1370,1372],{"id":1371},"discount-effects","Discount effects",[82,1374,1375,1377],{},[86,1376,237],{}," provides helpers for the common ways to create allocations:",[114,1379,1381],{"className":116,"code":1380,"language":118,"meta":119,"style":119},"\u002F\u002F EUR 5.00 distributed proportionally across all cart lines.\n$context->fixedAmountOff(Price::of(500));\n\n\u002F\u002F 10% distributed proportionally across all cart lines.\n$context->percentageOff(10);\n\n\u002F\u002F EUR 3.00 off the selected shipping option.\n$context->fixedAmountOffShipping(Price::of(300));\n\n\u002F\u002F 100% off the selected shipping option.\n$context->percentageOffShipping(100);\n",[86,1382,1383,1388,1413,1417,1422,1438,1442,1447,1473,1477,1482],{"__ignoreMap":119},[123,1384,1385],{"class":125,"line":126},[123,1386,1387],{"class":1009},"\u002F\u002F EUR 5.00 distributed proportionally across all cart lines.\n",[123,1389,1390,1392,1394,1396,1398,1400,1402,1404,1406,1408,1410],{"class":125,"line":137},[123,1391,973],{"class":129},[123,1393,311],{"class":133},[123,1395,341],{"class":129},[123,1397,455],{"class":299},[123,1399,303],{"class":129},[123,1401,255],{"class":151},[123,1403,462],{"class":129},[123,1405,465],{"class":299},[123,1407,303],{"class":129},[123,1409,99],{"class":147},[123,1411,1412],{"class":129},"));\n",[123,1414,1415],{"class":125,"line":144},[123,1416,141],{"emptyLinePlaceholder":140},[123,1418,1419],{"class":125,"line":164},[123,1420,1421],{"class":1009},"\u002F\u002F 10% distributed proportionally across all cart lines.\n",[123,1423,1424,1426,1428,1430,1432,1434,1436],{"class":125,"line":169},[123,1425,973],{"class":129},[123,1427,311],{"class":133},[123,1429,341],{"class":129},[123,1431,931],{"class":299},[123,1433,303],{"class":129},[123,1435,936],{"class":147},[123,1437,600],{"class":129},[123,1439,1440],{"class":125,"line":198},[123,1441,141],{"emptyLinePlaceholder":140},[123,1443,1444],{"class":125,"line":220},[123,1445,1446],{"class":1009},"\u002F\u002F EUR 3.00 off the selected shipping option.\n",[123,1448,1449,1451,1453,1455,1458,1460,1462,1464,1466,1468,1471],{"class":125,"line":242},[123,1450,973],{"class":129},[123,1452,311],{"class":133},[123,1454,341],{"class":129},[123,1456,1457],{"class":299},"fixedAmountOffShipping",[123,1459,303],{"class":129},[123,1461,255],{"class":151},[123,1463,462],{"class":129},[123,1465,465],{"class":299},[123,1467,303],{"class":129},[123,1469,1470],{"class":147},"300",[123,1472,1412],{"class":129},[123,1474,1475],{"class":125,"line":260},[123,1476,141],{"emptyLinePlaceholder":140},[123,1478,1479],{"class":125,"line":265},[123,1480,1481],{"class":1009},"\u002F\u002F 100% off the selected shipping option.\n",[123,1483,1484,1486,1488,1490,1493,1495,1498],{"class":125,"line":284},[123,1485,973],{"class":129},[123,1487,311],{"class":133},[123,1489,341],{"class":129},[123,1491,1492],{"class":299},"percentageOffShipping",[123,1494,303],{"class":129},[123,1496,1497],{"class":147},"100",[123,1499,600],{"class":129},[82,1501,1502,1503,1506],{},"Percentages may be integers or decimal strings such as ",[86,1504,1505],{},"'12.5'",". Calculated\namounts are rounded down to whole minor units, and proportional allocation\ndistributes any remainder deterministically.",[82,1508,1509],{},"Product discounts can be restricted with a callback that receives each cart\nitem:",[114,1511,1513],{"className":116,"code":1512,"language":118,"meta":119,"style":119},"allocations: $context->percentageOff(\n    20,\n    fn ($item) => $item->product->slug === 'featured-product',\n),\n",[86,1514,1515,1533,1540,1580],{"__ignoreMap":119},[123,1516,1517,1520,1523,1525,1527,1529,1531],{"class":125,"line":126},[123,1518,1519],{"class":151},"allocations",[123,1521,1522],{"class":133},": ",[123,1524,973],{"class":129},[123,1526,311],{"class":133},[123,1528,341],{"class":129},[123,1530,931],{"class":299},[123,1532,399],{"class":129},[123,1534,1535,1538],{"class":125,"line":137},[123,1536,1537],{"class":147},"    20",[123,1539,421],{"class":129},[123,1541,1542,1545,1547,1550,1552,1554,1556,1558,1560,1563,1565,1568,1571,1573,1576,1578],{"class":125,"line":144},[123,1543,1544],{"class":268},"    fn",[123,1546,336],{"class":129},[123,1548,1549],{"class":133},"item",[123,1551,361],{"class":129},[123,1553,1195],{"class":129},[123,1555,308],{"class":129},[123,1557,1549],{"class":133},[123,1559,341],{"class":129},[123,1561,1562],{"class":133},"product",[123,1564,341],{"class":129},[123,1566,1567],{"class":133},"slug ",[123,1569,1570],{"class":129},"===",[123,1572,411],{"class":129},[123,1574,1575],{"class":414},"featured-product",[123,1577,418],{"class":129},[123,1579,421],{"class":129},[123,1581,1582],{"class":125,"line":164},[123,1583,939],{"class":129},[82,1585,1586],{},"A shipping helper returns no allocations when the cart has no selected shipping\noption. Fixed discounts are capped at the eligible amount.",[102,1588,1590],{"id":1589},"custom-allocations","Custom allocations",[82,1592,1593],{},"For rules that do not fit the helpers, create allocations directly. Targets\nmust belong to the evaluated cart.",[114,1595,1597],{"className":116,"code":1596,"language":118,"meta":119,"style":119},"use Larasell\\Larasell\\Discounts\\DiscountAllocation;\n\n$item = $context->items->first();\n\nreturn new DiscountResult(\n    identifier: 'first-line-discount',\n    name: 'First line discount',\n    allocations: [\n        new DiscountAllocation(\n            target: $context->target($item),\n            amount: Price::of(250),\n        ),\n    ],\n);\n",[86,1598,1599,1620,1624,1649,1653,1664,1680,1696,1706,1716,1738,1759,1764,1769],{"__ignoreMap":119},[123,1600,1601,1603,1605,1607,1609,1611,1613,1615,1618],{"class":125,"line":126},[123,1602,172],{"class":147},[123,1604,175],{"class":133},[123,1606,155],{"class":129},[123,1608,180],{"class":133},[123,1610,155],{"class":129},[123,1612,211],{"class":133},[123,1614,155],{"class":129},[123,1616,1617],{"class":133},"DiscountAllocation",[123,1619,161],{"class":129},[123,1621,1622],{"class":125,"line":137},[123,1623,141],{"emptyLinePlaceholder":140},[123,1625,1626,1628,1631,1633,1635,1637,1639,1642,1644,1647],{"class":125,"line":144},[123,1627,973],{"class":129},[123,1629,1630],{"class":133},"item ",[123,1632,1174],{"class":129},[123,1634,308],{"class":129},[123,1636,311],{"class":133},[123,1638,341],{"class":129},[123,1640,1641],{"class":133},"items",[123,1643,341],{"class":129},[123,1645,1646],{"class":299},"first",[123,1648,1332],{"class":129},[123,1650,1651],{"class":125,"line":164},[123,1652,141],{"emptyLinePlaceholder":140},[123,1654,1655,1658,1660,1662],{"class":125,"line":169},[123,1656,1657],{"class":332},"return",[123,1659,393],{"class":147},[123,1661,396],{"class":151},[123,1663,399],{"class":129},[123,1665,1666,1669,1671,1673,1676,1678],{"class":125,"line":198},[123,1667,1668],{"class":151},"    identifier",[123,1670,408],{"class":129},[123,1672,411],{"class":129},[123,1674,1675],{"class":414},"first-line-discount",[123,1677,418],{"class":129},[123,1679,421],{"class":129},[123,1681,1682,1685,1687,1689,1692,1694],{"class":125,"line":220},[123,1683,1684],{"class":151},"    name",[123,1686,408],{"class":129},[123,1688,411],{"class":129},[123,1690,1691],{"class":414},"First line discount",[123,1693,418],{"class":129},[123,1695,421],{"class":129},[123,1697,1698,1701,1703],{"class":125,"line":242},[123,1699,1700],{"class":151},"    allocations",[123,1702,408],{"class":129},[123,1704,1705],{"class":129}," [\n",[123,1707,1708,1711,1714],{"class":125,"line":260},[123,1709,1710],{"class":147},"        new",[123,1712,1713],{"class":151}," DiscountAllocation",[123,1715,399],{"class":129},[123,1717,1718,1721,1723,1725,1727,1729,1732,1734,1736],{"class":125,"line":265},[123,1719,1720],{"class":151},"            target",[123,1722,408],{"class":129},[123,1724,308],{"class":129},[123,1726,311],{"class":133},[123,1728,341],{"class":129},[123,1730,1731],{"class":299},"target",[123,1733,1242],{"class":129},[123,1735,1549],{"class":133},[123,1737,939],{"class":129},[123,1739,1740,1743,1745,1748,1750,1752,1754,1757],{"class":125,"line":284},[123,1741,1742],{"class":151},"            amount",[123,1744,408],{"class":129},[123,1746,1747],{"class":151}," Price",[123,1749,462],{"class":129},[123,1751,465],{"class":299},[123,1753,303],{"class":129},[123,1755,1756],{"class":147},"250",[123,1758,939],{"class":129},[123,1760,1761],{"class":125,"line":290},[123,1762,1763],{"class":129},"        ),\n",[123,1765,1766],{"class":125,"line":323},[123,1767,1768],{"class":129},"    ],\n",[123,1770,1771],{"class":125,"line":329},[123,1772,600],{"class":129},[82,1774,1775],{},"Every promotion line identifies both its merchandising product and concrete\npurchasable variant. Use the context selectors for common variant-aware rules:",[114,1777,1779],{"className":116,"code":1778,"language":118,"meta":119,"style":119},"$productLines = $context->forProduct($product);\n$oneCombination = $context->forVariant($variant);\n$smallLines = $context->withAttributeValue($small);\n\n$context->percentageOff(\n    20,\n    fn ($item) => $smallLines->contains(fn ($line) => $line->is($item)),\n);\n",[86,1780,1781,1805,1830,1855,1859,1871,1877,1927],{"__ignoreMap":119},[123,1782,1783,1785,1788,1790,1792,1794,1796,1799,1801,1803],{"class":125,"line":126},[123,1784,973],{"class":129},[123,1786,1787],{"class":133},"productLines ",[123,1789,1174],{"class":129},[123,1791,308],{"class":129},[123,1793,311],{"class":133},[123,1795,341],{"class":129},[123,1797,1798],{"class":299},"forProduct",[123,1800,1242],{"class":129},[123,1802,1562],{"class":133},[123,1804,600],{"class":129},[123,1806,1807,1809,1812,1814,1816,1818,1820,1823,1825,1828],{"class":125,"line":137},[123,1808,973],{"class":129},[123,1810,1811],{"class":133},"oneCombination ",[123,1813,1174],{"class":129},[123,1815,308],{"class":129},[123,1817,311],{"class":133},[123,1819,341],{"class":129},[123,1821,1822],{"class":299},"forVariant",[123,1824,1242],{"class":129},[123,1826,1827],{"class":133},"variant",[123,1829,600],{"class":129},[123,1831,1832,1834,1837,1839,1841,1843,1845,1848,1850,1853],{"class":125,"line":144},[123,1833,973],{"class":129},[123,1835,1836],{"class":133},"smallLines ",[123,1838,1174],{"class":129},[123,1840,308],{"class":129},[123,1842,311],{"class":133},[123,1844,341],{"class":129},[123,1846,1847],{"class":299},"withAttributeValue",[123,1849,1242],{"class":129},[123,1851,1852],{"class":133},"small",[123,1854,600],{"class":129},[123,1856,1857],{"class":125,"line":164},[123,1858,141],{"emptyLinePlaceholder":140},[123,1860,1861,1863,1865,1867,1869],{"class":125,"line":169},[123,1862,973],{"class":129},[123,1864,311],{"class":133},[123,1866,341],{"class":129},[123,1868,931],{"class":299},[123,1870,399],{"class":129},[123,1872,1873,1875],{"class":125,"line":198},[123,1874,1537],{"class":147},[123,1876,421],{"class":129},[123,1878,1879,1881,1883,1885,1887,1889,1891,1894,1896,1899,1901,1904,1906,1908,1910,1912,1914,1916,1918,1921,1923,1925],{"class":125,"line":220},[123,1880,1544],{"class":268},[123,1882,336],{"class":129},[123,1884,1549],{"class":133},[123,1886,361],{"class":129},[123,1888,1195],{"class":129},[123,1890,308],{"class":129},[123,1892,1893],{"class":133},"smallLines",[123,1895,341],{"class":129},[123,1897,1898],{"class":299},"contains",[123,1900,303],{"class":129},[123,1902,1903],{"class":268},"fn",[123,1905,336],{"class":129},[123,1907,125],{"class":133},[123,1909,361],{"class":129},[123,1911,1195],{"class":129},[123,1913,308],{"class":129},[123,1915,125],{"class":133},[123,1917,341],{"class":129},[123,1919,1920],{"class":299},"is",[123,1922,1242],{"class":129},[123,1924,1549],{"class":133},[123,1926,473],{"class":129},[123,1928,1929],{"class":125,"line":242},[123,1930,600],{"class":129},[82,1932,1933],{},"Allocation targets remain cart-line IDs, so two variants of the same product\nreceive independent, stable discount allocations.",[82,1935,1936],{},"An allocation amount must be positive. A result may contain at most one\nallocation for each target. The promotion manager rejects targets outside the\ncart.",[102,1938,1940],{"id":1939},"reading-cart-discounts","Reading cart discounts",[82,1942,1943],{},"The cart exposes the results and calculated totals:",[114,1945,1947],{"className":116,"code":1946,"language":118,"meta":119,"style":119},"$cart->subtotal();      \u002F\u002F Merchandise before discounts\n$cart->discounts();     \u002F\u002F Collection of DiscountResult objects\n$cart->discountTotal(); \u002F\u002F Effective discount amount\n$cart->total();         \u002F\u002F Merchandise + shipping - discounts\n",[86,1948,1949,1964,1980,1996],{"__ignoreMap":119},[123,1950,1951,1953,1955,1957,1959,1961],{"class":125,"line":126},[123,1952,973],{"class":129},[123,1954,976],{"class":133},[123,1956,341],{"class":129},[123,1958,344],{"class":299},[123,1960,1006],{"class":129},[123,1962,1963],{"class":1009},"      \u002F\u002F Merchandise before discounts\n",[123,1965,1966,1968,1970,1972,1975,1977],{"class":125,"line":137},[123,1967,973],{"class":129},[123,1969,976],{"class":133},[123,1971,341],{"class":129},[123,1973,1974],{"class":299},"discounts",[123,1976,1006],{"class":129},[123,1978,1979],{"class":1009},"     \u002F\u002F Collection of DiscountResult objects\n",[123,1981,1982,1984,1986,1988,1991,1993],{"class":125,"line":144},[123,1983,973],{"class":129},[123,1985,976],{"class":133},[123,1987,341],{"class":129},[123,1989,1990],{"class":299},"discountTotal",[123,1992,1006],{"class":129},[123,1994,1995],{"class":1009}," \u002F\u002F Effective discount amount\n",[123,1997,1998,2000,2002,2004,2007,2009],{"class":125,"line":164},[123,1999,973],{"class":129},[123,2001,976],{"class":133},[123,2003,341],{"class":129},[123,2005,2006],{"class":299},"total",[123,2008,1006],{"class":129},[123,2010,2011],{"class":1009},"         \u002F\u002F Merchandise + shipping - discounts\n",[82,2013,2014],{},"Each result contains its identifier, name, allocations, total, and an optional\nnormalized code:",[114,2016,2018],{"className":116,"code":2017,"language":118,"meta":119,"style":119},"foreach ($cart->discounts() as $discount) {\n    $discount->identifier;\n    $discount->name;\n    $discount->code; \u002F\u002F null for automatic promotions\n    $discount->total();\n\n    foreach ($discount->allocations as $allocation) {\n        $allocation->target;\n        $allocation->amount;\n    }\n}\n",[86,2019,2020,2047,2060,2073,2089,2101,2105,2131,2143,2155,2159],{"__ignoreMap":119},[123,2021,2022,2025,2027,2029,2031,2033,2035,2038,2040,2043,2045],{"class":125,"line":126},[123,2023,2024],{"class":332},"foreach",[123,2026,336],{"class":129},[123,2028,976],{"class":133},[123,2030,341],{"class":129},[123,2032,1974],{"class":299},[123,2034,352],{"class":129},[123,2036,2037],{"class":129}," as",[123,2039,308],{"class":129},[123,2041,2042],{"class":133},"discount",[123,2044,361],{"class":129},[123,2046,364],{"class":129},[123,2048,2049,2051,2053,2055,2058],{"class":125,"line":137},[123,2050,581],{"class":129},[123,2052,2042],{"class":133},[123,2054,341],{"class":129},[123,2056,2057],{"class":133},"identifier",[123,2059,161],{"class":129},[123,2061,2062,2064,2066,2068,2071],{"class":125,"line":144},[123,2063,581],{"class":129},[123,2065,2042],{"class":133},[123,2067,341],{"class":129},[123,2069,2070],{"class":133},"name",[123,2072,161],{"class":129},[123,2074,2075,2077,2079,2081,2083,2086],{"class":125,"line":164},[123,2076,581],{"class":129},[123,2078,2042],{"class":133},[123,2080,341],{"class":129},[123,2082,86],{"class":133},[123,2084,2085],{"class":129},";",[123,2087,2088],{"class":1009}," \u002F\u002F null for automatic promotions\n",[123,2090,2091,2093,2095,2097,2099],{"class":125,"line":169},[123,2092,581],{"class":129},[123,2094,2042],{"class":133},[123,2096,341],{"class":129},[123,2098,2006],{"class":299},[123,2100,1332],{"class":129},[123,2102,2103],{"class":125,"line":198},[123,2104,141],{"emptyLinePlaceholder":140},[123,2106,2107,2110,2112,2114,2116,2119,2122,2124,2127,2129],{"class":125,"line":220},[123,2108,2109],{"class":332},"    foreach",[123,2111,336],{"class":129},[123,2113,2042],{"class":133},[123,2115,341],{"class":129},[123,2117,2118],{"class":133},"allocations ",[123,2120,2121],{"class":129},"as",[123,2123,308],{"class":129},[123,2125,2126],{"class":133},"allocation",[123,2128,361],{"class":129},[123,2130,364],{"class":129},[123,2132,2133,2135,2137,2139,2141],{"class":125,"line":242},[123,2134,1233],{"class":129},[123,2136,2126],{"class":133},[123,2138,341],{"class":129},[123,2140,1731],{"class":133},[123,2142,161],{"class":129},[123,2144,2145,2147,2149,2151,2153],{"class":125,"line":260},[123,2146,1233],{"class":129},[123,2148,2126],{"class":133},[123,2150,341],{"class":129},[123,2152,349],{"class":133},[123,2154,161],{"class":129},[123,2156,2157],{"class":125,"line":265},[123,2158,485],{"class":129},[123,2160,2161],{"class":125,"line":284},[123,2162,491],{"class":129},[82,2164,2165],{},"Promotions are recalculated from current cart data on every call. Do not treat a\ncart result as a historical record.",[102,2167,2169],{"id":2168},"stacking-promotions","Stacking promotions",[82,2171,2172,2173,2176],{},"Promotions are stackable by default. Implement ",[86,2174,2175],{},"HasPriority"," to evaluate a\npromotion before lower-priority promotions:",[114,2178,2180],{"className":116,"code":2179,"language":118,"meta":119,"style":119},"use Larasell\\Larasell\\Contracts\\Promotions\\HasPriority;\n\nfinal class SummerSale implements HasPriority, Promotion\n{\n    public function priority(): int\n    {\n        return 100;\n    }\n\n    \u002F\u002F ...\n}\n",[86,2181,2182,2206,2210,2228,2232,2246,2250,2259,2263,2267,2272],{"__ignoreMap":119},[123,2183,2184,2186,2188,2190,2192,2194,2196,2198,2200,2202,2204],{"class":125,"line":126},[123,2185,172],{"class":147},[123,2187,175],{"class":133},[123,2189,155],{"class":129},[123,2191,180],{"class":133},[123,2193,155],{"class":129},[123,2195,185],{"class":133},[123,2197,155],{"class":129},[123,2199,158],{"class":133},[123,2201,155],{"class":129},[123,2203,2175],{"class":133},[123,2205,161],{"class":129},[123,2207,2208],{"class":125,"line":137},[123,2209,141],{"emptyLinePlaceholder":140},[123,2211,2212,2214,2216,2219,2221,2224,2226],{"class":125,"line":144},[123,2213,269],{"class":268},[123,2215,272],{"class":268},[123,2217,2218],{"class":151}," SummerSale",[123,2220,278],{"class":268},[123,2222,2223],{"class":151}," HasPriority",[123,2225,761],{"class":129},[123,2227,281],{"class":151},[123,2229,2230],{"class":125,"line":164},[123,2231,287],{"class":129},[123,2233,2234,2236,2238,2241,2243],{"class":125,"line":169},[123,2235,293],{"class":268},[123,2237,296],{"class":268},[123,2239,2240],{"class":299}," priority",[123,2242,779],{"class":129},[123,2244,2245],{"class":147}," int\n",[123,2247,2248],{"class":125,"line":198},[123,2249,326],{"class":129},[123,2251,2252,2254,2257],{"class":125,"line":220},[123,2253,390],{"class":332},[123,2255,2256],{"class":147}," 100",[123,2258,161],{"class":129},[123,2260,2261],{"class":125,"line":242},[123,2262,485],{"class":129},[123,2264,2265],{"class":125,"line":260},[123,2266,141],{"emptyLinePlaceholder":140},[123,2268,2269],{"class":125,"line":265},[123,2270,2271],{"class":1009},"    \u002F\u002F ...\n",[123,2273,2274],{"class":125,"line":284},[123,2275,491],{"class":129},[82,2277,2278,2279,2282],{},"Higher numeric priorities run first. Promotions without this interface have a\npriority of ",[86,2280,2281],{},"0",", and registration order resolves equal priorities. Earlier\npromotions receive their allocations first. The manager caps the combined\ndiscount at each product or shipping target, so later promotions cannot make\nthat target negative.",[82,2284,108,2285,2288],{},[86,2286,2287],{},"ShouldBeExclusive"," marker interface when a promotion must be\nused alone:",[114,2290,2292],{"className":116,"code":2291,"language":118,"meta":119,"style":119},"use Larasell\\Larasell\\Contracts\\Promotions\\ShouldBeExclusive;\n\nfinal class WelcomeOffer implements Promotion, ShouldBeExclusive\n{\n    \u002F\u002F ...\n}\n",[86,2293,2294,2318,2322,2341,2345,2349],{"__ignoreMap":119},[123,2295,2296,2298,2300,2302,2304,2306,2308,2310,2312,2314,2316],{"class":125,"line":126},[123,2297,172],{"class":147},[123,2299,175],{"class":133},[123,2301,155],{"class":129},[123,2303,180],{"class":133},[123,2305,155],{"class":129},[123,2307,185],{"class":133},[123,2309,155],{"class":129},[123,2311,158],{"class":133},[123,2313,155],{"class":129},[123,2315,2287],{"class":133},[123,2317,161],{"class":129},[123,2319,2320],{"class":125,"line":137},[123,2321,141],{"emptyLinePlaceholder":140},[123,2323,2324,2326,2328,2331,2333,2336,2338],{"class":125,"line":144},[123,2325,269],{"class":268},[123,2327,272],{"class":268},[123,2329,2330],{"class":151}," WelcomeOffer",[123,2332,278],{"class":268},[123,2334,2335],{"class":151}," Promotion",[123,2337,761],{"class":129},[123,2339,2340],{"class":151}," ShouldBeExclusive\n",[123,2342,2343],{"class":125,"line":164},[123,2344,287],{"class":129},[123,2346,2347],{"class":125,"line":169},[123,2348,2271],{"class":1009},[123,2350,2351],{"class":125,"line":198},[123,2352,491],{"class":129},[82,2354,2355],{},"When one or more exclusive promotions apply, only the applicable exclusive\npromotion with the highest priority is used. Registration order resolves a tie.\nAn inapplicable exclusive promotion does not affect other promotions.",[102,2357,2359],{"id":2358},"availability-windows","Availability windows",[82,2361,614,2362,2365,2366,2369],{},[86,2363,2364],{},"HasAvailability"," when a promotion may only apply during a specific\nperiod. The single ",[86,2367,2368],{},"window()"," method returns its optional boundaries:",[114,2371,2373],{"className":116,"code":2372,"language":118,"meta":119,"style":119},"use Illuminate\\Support\\Carbon;\nuse Larasell\\Larasell\\Contracts\\Promotions\\HasAvailability;\n\nfinal class SeptemberSale implements HasAvailability, Promotion\n{\n    public function window(): array\n    {\n        return [\n            'starts_at' => Carbon::parse('2026-09-01 00:00:00'),\n            'ends_at' => Carbon::parse('2026-09-30 23:59:59'),\n        ];\n    }\n\n    \u002F\u002F ...\n}\n",[86,2374,2375,2393,2417,2421,2439,2443,2457,2461,2467,2498,2526,2531,2535,2539,2543],{"__ignoreMap":119},[123,2376,2377,2379,2381,2383,2386,2388,2391],{"class":125,"line":126},[123,2378,172],{"class":147},[123,2380,1067],{"class":133},[123,2382,155],{"class":129},[123,2384,2385],{"class":133},"Support",[123,2387,155],{"class":129},[123,2389,2390],{"class":133},"Carbon",[123,2392,161],{"class":129},[123,2394,2395,2397,2399,2401,2403,2405,2407,2409,2411,2413,2415],{"class":125,"line":137},[123,2396,172],{"class":147},[123,2398,175],{"class":133},[123,2400,155],{"class":129},[123,2402,180],{"class":133},[123,2404,155],{"class":129},[123,2406,185],{"class":133},[123,2408,155],{"class":129},[123,2410,158],{"class":133},[123,2412,155],{"class":129},[123,2414,2364],{"class":133},[123,2416,161],{"class":129},[123,2418,2419],{"class":125,"line":144},[123,2420,141],{"emptyLinePlaceholder":140},[123,2422,2423,2425,2427,2430,2432,2435,2437],{"class":125,"line":164},[123,2424,269],{"class":268},[123,2426,272],{"class":268},[123,2428,2429],{"class":151}," SeptemberSale",[123,2431,278],{"class":268},[123,2433,2434],{"class":151}," HasAvailability",[123,2436,761],{"class":129},[123,2438,281],{"class":151},[123,2440,2441],{"class":125,"line":169},[123,2442,287],{"class":129},[123,2444,2445,2447,2449,2452,2454],{"class":125,"line":198},[123,2446,293],{"class":268},[123,2448,296],{"class":268},[123,2450,2451],{"class":299}," window",[123,2453,779],{"class":129},[123,2455,2456],{"class":147}," array\n",[123,2458,2459],{"class":125,"line":220},[123,2460,326],{"class":129},[123,2462,2463,2465],{"class":125,"line":242},[123,2464,390],{"class":332},[123,2466,1705],{"class":129},[123,2468,2469,2472,2475,2477,2479,2482,2484,2487,2489,2491,2494,2496],{"class":125,"line":260},[123,2470,2471],{"class":129},"            '",[123,2473,2474],{"class":414},"starts_at",[123,2476,418],{"class":129},[123,2478,1195],{"class":129},[123,2480,2481],{"class":151}," Carbon",[123,2483,462],{"class":129},[123,2485,2486],{"class":299},"parse",[123,2488,303],{"class":129},[123,2490,418],{"class":129},[123,2492,2493],{"class":414},"2026-09-01 00:00:00",[123,2495,418],{"class":129},[123,2497,939],{"class":129},[123,2499,2500,2502,2505,2507,2509,2511,2513,2515,2517,2519,2522,2524],{"class":125,"line":265},[123,2501,2471],{"class":129},[123,2503,2504],{"class":414},"ends_at",[123,2506,418],{"class":129},[123,2508,1195],{"class":129},[123,2510,2481],{"class":151},[123,2512,462],{"class":129},[123,2514,2486],{"class":299},[123,2516,303],{"class":129},[123,2518,418],{"class":129},[123,2520,2521],{"class":414},"2026-09-30 23:59:59",[123,2523,418],{"class":129},[123,2525,939],{"class":129},[123,2527,2528],{"class":125,"line":284},[123,2529,2530],{"class":129},"        ];\n",[123,2532,2533],{"class":125,"line":290},[123,2534,485],{"class":129},[123,2536,2537],{"class":125,"line":323},[123,2538,141],{"emptyLinePlaceholder":140},[123,2540,2541],{"class":125,"line":329},[123,2542,2271],{"class":1009},[123,2544,2545],{"class":125,"line":367},[123,2546,491],{"class":129},[82,2548,2549,2550,2553,2554,2556,2557,2559],{},"Both boundaries are inclusive and must implement ",[86,2551,2552],{},"CarbonInterface",". Either\n",[86,2555,2474],{}," or ",[86,2558,2504],{}," may be omitted for an open-ended window, but at least\none boundary is required. Coded promotions outside their availability window\ncannot be attached to a cart. Previously attached codes remain stored but stop\nproducing a discount while their promotion is unavailable.",[102,2561,2563],{"id":2562},"redemption-limits","Redemption limits",[82,2565,614,2566,2569],{},[86,2567,2568],{},"HasRedemptionLimit"," to cap how many orders can use a promotion:",[114,2571,2573],{"className":116,"code":2572,"language":118,"meta":119,"style":119},"use Larasell\\Larasell\\Contracts\\Promotions\\HasRedemptionLimit;\n\nfinal class LimitedSummerSale implements HasRedemptionLimit, Promotion\n{\n    public function limit(): int|array\n    {\n        return 100;\n    }\n\n    \u002F\u002F ...\n}\n",[86,2574,2575,2599,2603,2621,2625,2645,2649,2657,2661,2665,2669],{"__ignoreMap":119},[123,2576,2577,2579,2581,2583,2585,2587,2589,2591,2593,2595,2597],{"class":125,"line":126},[123,2578,172],{"class":147},[123,2580,175],{"class":133},[123,2582,155],{"class":129},[123,2584,180],{"class":133},[123,2586,155],{"class":129},[123,2588,185],{"class":133},[123,2590,155],{"class":129},[123,2592,158],{"class":133},[123,2594,155],{"class":129},[123,2596,2568],{"class":133},[123,2598,161],{"class":129},[123,2600,2601],{"class":125,"line":137},[123,2602,141],{"emptyLinePlaceholder":140},[123,2604,2605,2607,2609,2612,2614,2617,2619],{"class":125,"line":144},[123,2606,269],{"class":268},[123,2608,272],{"class":268},[123,2610,2611],{"class":151}," LimitedSummerSale",[123,2613,278],{"class":268},[123,2615,2616],{"class":151}," HasRedemptionLimit",[123,2618,761],{"class":129},[123,2620,281],{"class":151},[123,2622,2623],{"class":125,"line":164},[123,2624,287],{"class":129},[123,2626,2627,2629,2631,2634,2636,2639,2642],{"class":125,"line":169},[123,2628,293],{"class":268},[123,2630,296],{"class":268},[123,2632,2633],{"class":299}," limit",[123,2635,779],{"class":129},[123,2637,2638],{"class":147}," int",[123,2640,2641],{"class":129},"|",[123,2643,2644],{"class":147},"array\n",[123,2646,2647],{"class":125,"line":198},[123,2648,326],{"class":129},[123,2650,2651,2653,2655],{"class":125,"line":220},[123,2652,390],{"class":332},[123,2654,2256],{"class":147},[123,2656,161],{"class":129},[123,2658,2659],{"class":125,"line":242},[123,2660,485],{"class":129},[123,2662,2663],{"class":125,"line":260},[123,2664,141],{"emptyLinePlaceholder":140},[123,2666,2667],{"class":125,"line":265},[123,2668,2271],{"class":1009},[123,2670,2671],{"class":125,"line":284},[123,2672,491],{"class":129},[82,2674,2675],{},"A plain integer defines a global limit. Return an array to define global and\nper-customer limits together:",[114,2677,2679],{"className":116,"code":2678,"language":118,"meta":119,"style":119},"public function limit(): int|array\n{\n    return [\n        'global' => 1000,\n        'customer' => 1,\n    ];\n}\n",[86,2680,2681,2697,2701,2707,2724,2740,2745],{"__ignoreMap":119},[123,2682,2683,2685,2687,2689,2691,2693,2695],{"class":125,"line":126},[123,2684,553],{"class":268},[123,2686,296],{"class":268},[123,2688,2633],{"class":299},[123,2690,779],{"class":129},[123,2692,2638],{"class":147},[123,2694,2641],{"class":129},[123,2696,2644],{"class":147},[123,2698,2699],{"class":125,"line":137},[123,2700,287],{"class":129},[123,2702,2703,2705],{"class":125,"line":144},[123,2704,1327],{"class":332},[123,2706,1705],{"class":129},[123,2708,2709,2712,2715,2717,2719,2722],{"class":125,"line":164},[123,2710,2711],{"class":129},"        '",[123,2713,2714],{"class":414},"global",[123,2716,418],{"class":129},[123,2718,1195],{"class":129},[123,2720,2721],{"class":147}," 1000",[123,2723,421],{"class":129},[123,2725,2726,2728,2731,2733,2735,2738],{"class":125,"line":169},[123,2727,2711],{"class":129},[123,2729,2730],{"class":414},"customer",[123,2732,418],{"class":129},[123,2734,1195],{"class":129},[123,2736,2737],{"class":147}," 1",[123,2739,421],{"class":129},[123,2741,2742],{"class":125,"line":198},[123,2743,2744],{"class":129},"    ];\n",[123,2746,2747],{"class":125,"line":220},[123,2748,491],{"class":129},[82,2750,2751,2752,2755],{},"Either array key may be omitted, so ",[86,2753,2754],{},"['customer' => 1]"," creates a\ncustomer-only limit. All configured limits must be positive integers.",[82,2757,2758,2759,2762],{},"By default, Larasell identifies a customer by ",[86,2760,2761],{},"customer_id"," when checkout\nprovides one, and otherwise by normalized email address. Applications can\nreplace this behavior by binding the resolver contract:",[114,2764,2767],{"className":116,"code":2765,"filename":2766,"language":118,"meta":119,"style":119},"use App\\Commerce\\PromotionCustomerResolver;\nuse Larasell\\Larasell\\Contracts\\Promotions\\PromotionCustomerResolver as PromotionCustomerResolverContract;\n\n$this->app->bind(\n    PromotionCustomerResolverContract::class,\n    PromotionCustomerResolver::class,\n);\n","app\u002FProviders\u002FAppServiceProvider.php",[86,2768,2769,2787,2816,2820,2835,2846,2857],{"__ignoreMap":119},[123,2770,2771,2773,2775,2777,2780,2782,2785],{"class":125,"line":126},[123,2772,172],{"class":147},[123,2774,152],{"class":133},[123,2776,155],{"class":129},[123,2778,2779],{"class":133},"Commerce",[123,2781,155],{"class":129},[123,2783,2784],{"class":133},"PromotionCustomerResolver",[123,2786,161],{"class":129},[123,2788,2789,2791,2793,2795,2797,2799,2801,2803,2805,2807,2809,2811,2814],{"class":125,"line":137},[123,2790,172],{"class":147},[123,2792,175],{"class":133},[123,2794,155],{"class":129},[123,2796,180],{"class":133},[123,2798,155],{"class":129},[123,2800,185],{"class":133},[123,2802,155],{"class":129},[123,2804,158],{"class":133},[123,2806,155],{"class":129},[123,2808,2784],{"class":133},[123,2810,2037],{"class":147},[123,2812,2813],{"class":151}," PromotionCustomerResolverContract",[123,2815,161],{"class":129},[123,2817,2818],{"class":125,"line":144},[123,2819,141],{"emptyLinePlaceholder":140},[123,2821,2822,2825,2828,2830,2833],{"class":125,"line":164},[123,2823,2824],{"class":129},"$this->",[123,2826,2827],{"class":133},"app",[123,2829,341],{"class":129},[123,2831,2832],{"class":299},"bind",[123,2834,399],{"class":129},[123,2836,2837,2840,2842,2844],{"class":125,"line":169},[123,2838,2839],{"class":151},"    PromotionCustomerResolverContract",[123,2841,462],{"class":129},[123,2843,597],{"class":147},[123,2845,421],{"class":129},[123,2847,2848,2851,2853,2855],{"class":125,"line":198},[123,2849,2850],{"class":151},"    PromotionCustomerResolver",[123,2852,462],{"class":129},[123,2854,597],{"class":147},[123,2856,421],{"class":129},[123,2858,2859],{"class":125,"line":220},[123,2860,600],{"class":129},[82,2862,2863],{},"The custom resolver implements:",[114,2865,2867],{"className":116,"code":2866,"language":118,"meta":119,"style":119},"public function resolve(?int $customerId, string $email): string;\n",[86,2868,2869],{"__ignoreMap":119},[123,2870,2871,2873,2875,2878,2881,2884,2886,2889,2891,2894,2896,2899,2901,2903],{"class":125,"line":126},[123,2872,553],{"class":268},[123,2874,296],{"class":268},[123,2876,2877],{"class":299}," resolve",[123,2879,2880],{"class":129},"(?",[123,2882,2883],{"class":147},"int",[123,2885,308],{"class":129},[123,2887,2888],{"class":133},"customerId",[123,2890,761],{"class":129},[123,2892,2893],{"class":147}," string",[123,2895,308],{"class":129},[123,2897,2898],{"class":133},"email",[123,2900,314],{"class":129},[123,2902,2893],{"class":147},[123,2904,161],{"class":129},[82,2906,2907],{},"It must return a stable, non-empty identifier for the customer.",[82,2909,2910,2911,2914,2915,2918,2919,2922,2923,2926,2927,2930],{},"Checkout reserves one use of each applied limited promotion. A successful\npayment permanently redeems it. Cancelling an unpaid order releases its\nreserved uses. Redeemed uses remain counted when an order is later refunded or\ncancelled. If global or per-customer capacity is exhausted, checkout throws\n",[86,2912,2913],{},"PromotionRedemptionLimitReachedException"," or\n",[86,2916,2917],{},"CustomerPromotionRedemptionLimitReachedException",". Catch\n",[86,2920,2921],{},"PromotionException"," at checkout the same way as ",[86,2924,2925],{},"CartException",". Corrupted\nredemption counters throw ",[86,2928,2929],{},"PromotionRedemptionIntegrityException",", which is not\na customer-facing promotion failure.",[82,2932,2933],{},"Expired promotion reservations are processed by this command:",[114,2935,2939],{"className":2936,"code":2937,"language":2938,"meta":119,"style":119},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","php artisan larasell:release-expired-promotions\n","bash",[86,2940,2941],{"__ignoreMap":119},[123,2942,2943,2945,2948],{"class":125,"line":126},[123,2944,118],{"class":151},[123,2946,2947],{"class":414}," artisan",[123,2949,2950],{"class":414}," larasell:release-expired-promotions\n",[82,2952,2953],{},"The package does not schedule the command. Add it to the application scheduler:",[114,2955,2958],{"className":116,"code":2956,"filename":2957,"language":118,"meta":119,"style":119},"use Illuminate\\Support\\Facades\\Schedule;\n\nSchedule::command('larasell:release-expired-promotions')\n    ->everyMinute()\n    ->withoutOverlapping();\n","routes\u002Fconsole.php",[86,2959,2960,2982,2986,3006,3017],{"__ignoreMap":119},[123,2961,2962,2964,2966,2968,2970,2972,2975,2977,2980],{"class":125,"line":126},[123,2963,172],{"class":147},[123,2965,1067],{"class":133},[123,2967,155],{"class":129},[123,2969,2385],{"class":133},[123,2971,155],{"class":129},[123,2973,2974],{"class":133},"Facades",[123,2976,155],{"class":129},[123,2978,2979],{"class":133},"Schedule",[123,2981,161],{"class":129},[123,2983,2984],{"class":125,"line":137},[123,2985,141],{"emptyLinePlaceholder":140},[123,2987,2988,2990,2992,2995,2997,2999,3002,3004],{"class":125,"line":144},[123,2989,2979],{"class":151},[123,2991,462],{"class":129},[123,2993,2994],{"class":299},"command",[123,2996,303],{"class":129},[123,2998,418],{"class":129},[123,3000,3001],{"class":414},"larasell:release-expired-promotions",[123,3003,418],{"class":129},[123,3005,1160],{"class":129},[123,3007,3008,3011,3014],{"class":125,"line":164},[123,3009,3010],{"class":129},"    ->",[123,3012,3013],{"class":299},"everyMinute",[123,3015,3016],{"class":129},"()\n",[123,3018,3019,3021,3024],{"class":125,"line":169},[123,3020,3010],{"class":129},[123,3022,3023],{"class":299},"withoutOverlapping",[123,3025,1332],{"class":129},[82,3027,3028,3029,3032,3033,1361],{},"An expired promotion reservation cancels its unpaid order and releases its\nreserved capacity. The reservation lifetime comes from the selected payment\nmethod's ",[86,3030,3031],{},"inventory_reservation_minutes"," setting. The command supports a\ncustom batch size with ",[86,3034,3035],{},"--batch-size=250",[102,3037,3039],{"id":3038},"order-snapshots","Order snapshots",[82,3041,3042,3043,3046,3047,3049,3050,1361],{},"Checkout recalculates promotions inside its database transaction. The order\nstores the final ",[86,3044,3045],{},"discount_total"," and a JSON snapshot in ",[86,3048,1974],{},". Each order\nitem stores its allocated ",[86,3051,3045],{},[114,3053,3055],{"className":116,"code":3054,"language":118,"meta":119,"style":119},"$order->subtotal;                 \u002F\u002F Merchandise before discounts\n$order->discount_total;           \u002F\u002F Product and shipping discounts\n$order->total;                    \u002F\u002F Final amount charged\n$order->items[0]->discount_total; \u002F\u002F Discount allocated to this line\n$order->discounts;                \u002F\u002F Promotion and allocation snapshots\n",[86,3056,3057,3073,3088,3103,3127],{"__ignoreMap":119},[123,3058,3059,3061,3064,3066,3068,3070],{"class":125,"line":126},[123,3060,973],{"class":129},[123,3062,3063],{"class":133},"order",[123,3065,341],{"class":129},[123,3067,344],{"class":133},[123,3069,2085],{"class":129},[123,3071,3072],{"class":1009},"                 \u002F\u002F Merchandise before discounts\n",[123,3074,3075,3077,3079,3081,3083,3085],{"class":125,"line":137},[123,3076,973],{"class":129},[123,3078,3063],{"class":133},[123,3080,341],{"class":129},[123,3082,3045],{"class":133},[123,3084,2085],{"class":129},[123,3086,3087],{"class":1009},"           \u002F\u002F Product and shipping discounts\n",[123,3089,3090,3092,3094,3096,3098,3100],{"class":125,"line":144},[123,3091,973],{"class":129},[123,3093,3063],{"class":133},[123,3095,341],{"class":129},[123,3097,2006],{"class":133},[123,3099,2085],{"class":129},[123,3101,3102],{"class":1009},"                    \u002F\u002F Final amount charged\n",[123,3104,3105,3107,3109,3111,3113,3115,3117,3120,3122,3124],{"class":125,"line":164},[123,3106,973],{"class":129},[123,3108,3063],{"class":133},[123,3110,341],{"class":129},[123,3112,1641],{"class":133},[123,3114,1248],{"class":129},[123,3116,2281],{"class":147},[123,3118,3119],{"class":129},"]->",[123,3121,3045],{"class":133},[123,3123,2085],{"class":129},[123,3125,3126],{"class":1009}," \u002F\u002F Discount allocated to this line\n",[123,3128,3129,3131,3133,3135,3137,3139],{"class":125,"line":169},[123,3130,973],{"class":129},[123,3132,3063],{"class":133},[123,3134,341],{"class":129},[123,3136,1974],{"class":133},[123,3138,2085],{"class":129},[123,3140,3141],{"class":1009},"                \u002F\u002F Promotion and allocation snapshots\n",[82,3143,3144,3145,3148,3149,3151],{},"Cart-line targets are translated to permanent order item IDs in the snapshot.\nShipping allocations use the ",[86,3146,3147],{},"shipping"," target and have no order item ID. These\nvalues remain unchanged when promotion classes or products change later. A\nsnapshot created by a coded promotion also contains its normalized ",[86,3150,86],{},";\nautomatic promotion snapshots omit that key.",[102,3153,3155],{"id":3154},"events","Events",[82,3157,3158],{},"Promotion lifecycle events are dispatched after their database transaction\ncommits:",[3160,3161,3162,3168,3173,3178,3183,3188],"ul",{},[3163,3164,3165],"li",{},[86,3166,3167],{},"Larasell\\Larasell\\Events\\PromotionCodeApplied",[3163,3169,3170],{},[86,3171,3172],{},"Larasell\\Larasell\\Events\\PromotionCodeRemoved",[3163,3174,3175],{},[86,3176,3177],{},"Larasell\\Larasell\\Events\\PromotionApplied",[3163,3179,3180],{},[86,3181,3182],{},"Larasell\\Larasell\\Events\\PromotionRedemptionReserved",[3163,3184,3185],{},[86,3186,3187],{},"Larasell\\Larasell\\Events\\PromotionRedemptionRedeemed",[3163,3189,3190],{},[86,3191,3192],{},"Larasell\\Larasell\\Events\\PromotionRedemptionReleased",[82,3194,3195,3196,3199,3200,3203],{},"Code events expose the affected ",[86,3197,3198],{},"$cart"," and normalized ",[86,3201,3202],{},"$code"," properties. They\nonly fire when the stored codes actually change, so applying an attached code\nor removing a missing code does not dispatch a duplicate event.",[82,3205,3206,3209,3210,3213,3214,3217,3218,3221],{},[86,3207,3208],{},"PromotionApplied"," exposes the ",[86,3211,3212],{},"$order"," and its ",[86,3215,3216],{},"$discount"," snapshot. One event\nis dispatched for each promotion recorded during checkout. Reading\n",[86,3219,3220],{},"$cart->discounts()"," does not dispatch events because cart promotions are\nrecalculated values rather than durable state changes.",[82,3223,3224,3225,3228],{},"Redemption events expose the affected redemption through their ",[86,3226,3227],{},"$redemption","\nproperty. They are dispatched once when limited promotion capacity is reserved\nduring checkout, permanently redeemed by successful payment, or released by\norder cancellation or expiration.",[3230,3231,3232],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":119,"searchDepth":126,"depth":137,"links":3234},[3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245],{"id":104,"depth":137,"text":105},{"id":497,"depth":137,"text":498},{"id":610,"depth":137,"text":611},{"id":1371,"depth":137,"text":1372},{"id":1589,"depth":137,"text":1590},{"id":1939,"depth":137,"text":1940},{"id":2168,"depth":137,"text":2169},{"id":2358,"depth":137,"text":2359},{"id":2562,"depth":137,"text":2563},{"id":3038,"depth":137,"text":3039},{"id":3154,"depth":137,"text":3155},"Define automatic and code-based promotions, allocate discounts, and read discount totals.","md",null,{},{"title":34,"description":3246},"L-hox0F3VuG41dDv8Rz3Wo-jcc5Bnl9GzsR3jw6kXFQ",[3253,3255],{"title":30,"path":31,"stem":32,"description":3254,"children":-1},"Fetch visible products and their attached categories.",{"title":38,"path":39,"stem":40,"description":3256,"children":-1},"Configure tax rates, classify products, estimate cart tax, and read order tax snapshots.",1789114878354]