Skip to content

2.0.0

Latest

Choose a tag to compare

@gp247net gp247net released this 22 Sep 00:01

feat!: port to gp247/core 3.0, with an atomic sale quota (2.0.0)

Version 1.0.0 could not be installed on core 3.0 at all: requireCore ["1.1"]
fails ExtensionInstaller's compatibility range, and the admin screen extended
the removed gp247-core::layout while paginating through the removed
gp247-core::component.pagination, driven by pjax/select2/SweetAlert that the
TailAdmin shell no longer loads.

Admin

  • Two-panel Livewire screen on the core ResourcePanel base, replacing the
    AdminLTE controller and its views. Route names are unchanged because the
    AdminMenu row written by install() points at admin_product_flash_sale.index.
  • Searchable product picker, flatpickr window WITH the hour (time-boxed selling
    needs it), price in the base currency, sold/quantity progress, store column on
    multi-store installs.
  • Validation the old screen never really had: its unique rule passed a quoted
    class name, which Laravel reads as a table name, so creating a sale hit a SQL
    error. Rules now cover one-sale-per-product, quantity >= sold, end after start,
    and a server-side check that the product belongs to the acting admin's store.

Quota integrity

  • Units are taken with a conditional UPDATE inside the order transaction. The old
    read-modify-write let two simultaneous checkouts both pass the advisory check
    and oversell the sale.
  • Units come back when the goods do: cancel, delete, and removing an order line
    now release them (wired from gp247/shop). Re-opening a cancelled order takes
    them again and is refused when the sale is spent. Before this, one cancelled
    order burned a slot for ever.

Visibility

  • The listing delegates to ShopProduct::buildQuery instead of querying the tables
    directly, so status, approval, store scope and the out-of-stock setting apply.
    On a marketplace the old query published unapproved and other stores' products.

Storefront

  • Own listing page (the template's product-list screen ignores $products and
    rebuilds its own query, so the old page listed the whole catalogue), registered
    as a LayoutBlock page-type and contributed to sitemap.xml.
  • The strip is Tailwind + the template's Alpine countdown; the jQuery countdown
    from a CDN is gone, as is jQuery itself.
  • The block is offered to templates by registering this plugin's directory as one
    more GP247TemplatePath source root — nothing is copied into app/GP247/Templates,
    so it works on read-only deployments and leaves nothing behind when removed.
    Registered from booted() so the site's own published files still win.

Install lifecycle

  • install() and update() share a re-entrant converge(); the table is created only
    when missing (installing used to drop it first, destroying every scheduled sale)
    and the menu row only when absent.
  • A fresh install also places the strip at the bottom of the home page for stores
    that have no such block. Deliberately not in converge(): where a block appears
    is the admin's decision, and an update must not overrule it.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com