agentsclimarketplace

Lw elallas integration

Skill Lonsdale201/wp-agent-skills/lw-plugins/lw-elallas-integration

Integrate with or extend "Elállás for WooCommerce" (elallas-for-woo), the LW-family EU/HU withdrawal case-management plugin for WooCommerce. Covers its elallas_* hooks, eligibility/deadline/B2B /delivery/order-number filters (including elallas_resolve_order_number), the 4-arg elallas_case_status_changed lifecycle action, PDF/email hooks, multilingual WPML/Polylang output, custom tables/order meta, WooCommerce logging, and LW Site Manager abilities. Use when building withdrawal-case compatibility, syncing cases to CRM/invoicing, supporting custom order numbers, or customizing its PDF/emails without editing the plugin.From its SKILL.md

Install
npx -y skills add Lonsdale201/wp-agent-skills --skill lw-elallas-integration

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 21 stars21 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

18.1 KB, ~4.3k tokens by cl100k_base, as published. Nobody here has run it

Elállás for WooCommerce — integration & extension

For developers making a plugin/theme work with Elállás for WooCommerce (elallas-for-woo, by uptools.io) — the online right-of-withdrawal (elállási jog) button + case-management plugin for WooCommerce, built for EU Directive 2023/2673 and 415/2025. (XII. 23.) Korm. rendelet. It manages a withdrawal "case" per order in its own tables and fires a small, clean set of elallas_* hooks for integrators.

This is an LW-family plugin — consume hooks, don't edit it

Namespace LightweightPlugins\Elallas, tables wp_lw_elallas_*, and it integrates with LW Site Manager — it's part of the LightweightPlugins family. Integrate by consuming its elallas_* hooks and reading its data; never patch the plugin. If you need an extension point that doesn't exist, request it upstream rather than editing.

Detect it:

if ( defined( 'ELALLAS_FOR_WOO_VERSION' ) ) { /* Elállás for WooCommerce active (1.0.12 tested) */ }

It requires WooCommerce 8.0+ and is HPOS-safe — every hook hands you a real \WC_Order, so use $order->get_*() (never post meta) — see wc-hpos-compatibility.

Extension point 1 — eligibility, deadline, B2B & order numbers

The first four filters decide whether an order may start a withdrawal and how the deadline is computed; they receive the \WC_Order. elallas_resolve_order_number runs earlier, before the order exists, and maps the customer-entered display order number to a WooCommerce order ID.

// Final say on eligibility (runs after the built-in checks).
add_filter( 'elallas_is_order_eligible', function ( bool $eligible, \WC_Order $order ): bool {
    // e.g. never allow withdrawal for a "digital-only" order:
    return $eligible && ! my_order_is_digital_only( $order );
}, 10, 2 );

// Override the withdrawal window (default: option 'deadline_days', 14).
add_filter( 'elallas_deadline_days', function ( int $days, \WC_Order $order ): int {
    return my_is_extended_returns_member( $order ) ? 30 : $days;
}, 10, 2 );

// Override the B2B/B2C heuristic (default: true if company name OR VAT number is set).
add_filter( 'elallas_is_order_b2b', function ( bool $is_b2b, \WC_Order $order ): bool {
    return $is_b2b || my_customer_is_business( $order->get_customer_id() );
}, 10, 2 );

// Override the delivery date used as a deadline basis.
add_filter( 'elallas_delivery_date', function ( $delivery, \WC_Order $order ) {
    return my_carrier_delivered_at( $order ) ?: $delivery;
}, 10, 2 );

// Resolve a customer-entered/display order number from another numbering plugin.
add_filter( 'elallas_resolve_order_number', function ( int $order_id, string $number ): int {
    if ( $order_id > 0 ) {
        return $order_id;
    }

    return my_numbering_plugin_find_order_id( $number ) ?: 0; // 0 = let Elállás fall through.
}, 10, 2 );

Verified: elallas_is_order_eligible at EligibilityChecker.php:67; elallas_deadline_days at :119 (default from Options::get('deadline_days', 14)); elallas_is_order_b2b at B2BDetector.php:40 (heuristic: company OR VAT filled); elallas_delivery_date at OrderAdapter.php:166; elallas_resolve_order_number at OrderAdapter.php:65.

Good to know about the built-in eligibility (so your filter composes correctly): by default only orders whose status is in eligible_statuses (default ['processing','completed']) qualify; an order with an already-open case is refused; logged-in users may only act on their own orders (guests fall back to an email match); and an expired deadline does NOT hard-block by default — it's flagged for manual review unless the expired_handling option is set to 'block' (EligibilityChecker.php:32-72). Your elallas_is_order_eligible filter is the final gate, so returning true can re-allow something the built-in checks denied — return $eligible && your_condition to only ever narrow.

Order identification uses the customer-visible order number, not always the internal WooCommerce order ID. In 1.0.12 the plugin first runs elallas_resolve_order_number, then supports WooCommerce Sequential Order Numbers Pro/free via find_order_by_order_number(), and only finally falls back to treating the entered value as the native order ID. The order details button passes $order->get_order_number() and the prefill keeps non-numeric prefixes/suffixes, so compatibility code must not cast the form value with absint().

Extension point 2 — react to the case lifecycle

A withdrawal case is created, optionally confirmed (two-step flow), then moved through admin statuses. Hook these to sync to a CRM, notify, or trigger invoicing/refund workflows.

// A new withdrawal case was submitted.
add_action( 'elallas_case_created', function ( int $case_id, int $order_id ): void {
    my_crm_open_return_ticket( $case_id, $order_id );
}, 10, 2 );

// The customer confirmed (two-step flow). Status is now auto_confirmed or manual_review.
add_action( 'elallas_case_confirmed', function ( int $case_id ): void { /* ... */ } );

// Any status transition (admin or system).
add_action( 'elallas_case_status_changed', function ( int $case_id, string $old, string $new, string $message ): void {
    if ( 'refund_pending' === $new ) { my_queue_refund( $case_id ); }

    if ( '' !== $message ) {
        my_crm_add_customer_visible_note( $case_id, $message );
    }
}, 10, 4 );

// Fired specifically for invoicing integrations.
add_action( 'elallas_invoicing_case_created', function ( int $case_id, int $order_id ): void { /* ... */ }, 10, 2 );

Verified: elallas_case_created($case_id, $order_id) at CaseService.php:83; elallas_case_confirmed($case_id) at :124; elallas_case_status_changed($case_id, $old_status, $new_status, $message) at :182; elallas_invoicing_case_created at Integrations/Invoicing.php:63.

The fourth $message argument is the optional admin note sent to the customer in the status-update e-mail. It is populated by the admin case detail form; REST and LW Site Manager status updates currently call change_status() without that message, so expect an empty string in automation-triggered transitions.

$case_id is a row ID in the custom wp_lw_elallas_cases table — NOT a post ID. Don't call get_post()/get_post_meta() on it. Read case data through the plugin's repositories/data or the tables (see reference.md). To find cases from an order, read the order meta the plugin writes: _lw_elallas_has_case ('yes'), _lw_elallas_case_ids (array of case IDs), _lw_elallas_deadline_status (CaseService.php:205-213). Treat that meta as read-only — let the plugin write it.

Case statuses (the CaseStatus set)

received → (auto_confirmed if the deadline is within, else manual_review) → admin moves it to accepted / rejected / awaiting_return / goods_received / refund_pending / closed / cancelled. All ten are the valid values elallas_case_status_changed will report; validate against them with the plugin's CaseStatus::is_valid(). Verified at CaseStatus.php:17-26. (Separately, DeadlineStatus is within / expired / unknown.)

Product/category/tag withdrawal exceptions

The plugin can mark products, product categories and product tags as excluded from withdrawal using _lw_elallas_excluded ('yes' / 'no') and _lw_elallas_exclusion_reason (reason key). Product-level meta wins first; otherwise ProductExclusion::evaluate() checks product_cat and product_tag term meta. Valid reason keys are unsealed, custom, digital, service, hygiene, perishable, sealed.

This does not auto-block the withdrawal flow. OrderSnapshotBuilder writes eligibility_flag = 'excepted' and eligibility_note = <reason label> into the case-item snapshot so the admin notification, case detail and order panel can flag it for manual review. If your integration imports products or bulk-edits exclusions, use the same meta keys via normal WP meta APIs, keep reason keys in the known set, and let the plugin build the snapshot.

Extension point 3 — customize the PDF & emails

// Filter the withdrawal PDF HTML before rendering (dompdf).
add_filter( 'elallas_pdf_html', function ( string $html, array $context ): string {
    return str_replace( '{{my_token}}', esc_html( my_value() ), $html );
}, 10, 2 );

Verified at PdfRenderer.php:40. The plugin's emails render through the standard woocommerce_email_header / woocommerce_email_footer hooks, so your existing WC email customizations apply — see wc-emails-classic.

PDF rendering uses the scoped LightweightPlugins\Elallas\Vendor\Dompdf\Dompdf class in release builds and falls back to global \Dompdf\Dompdf only for Composer-dependency installs. A PDF failure is logged and returns an empty string; it should not break case creation or e-mail sending.

Extension point 4 — multilingual output paths

The plugin detects WPML, Polylang and TranslatePress, but the important integration detail is runtime translation, not raw option reads. Admin-entered user-facing strings (button_label, confirm_label, legal_declaration, legal_confirmation, email_customer_extra) are explicitly registered/looked up for WPML and Polylang under the elallas-for-woo string context and printed through Multilingual::translate_option_string() / translate_string() on every output path; TranslatePress can translate the rendered output.

Do not add those option keys as WPML <admin-texts> in a compatibility layer. The plugin's wpml-config.xml intentionally declares only the withdrawal-exception product/term meta as copy and the [elallas_button] label shortcode attribute as translatable. Declaring the options too would double-register strings and fight the runtime translation path.

The stored withdrawal_page_id is resolved through Multilingual::object_id() so [elallas_button], the WooCommerce order button and front-end asset loading target the translated withdrawal page. Case submissions store the WPML/Polylang language code, and customer e-mails / status e-mails / PDFs switch to that case language while rendering; admin notifications switch to the shop default language.

Extension point 5 — elallas_boot

add_action( 'elallas_boot', function ( $plugin ): void {
    // Runs once the plugin has booted — safe place to wire your integration.
}, 10, 1 );

Verified at Plugin.php:64.

LW Site Manager abilities it exposes

If LW Site Manager is active, the plugin registers a elallas ability category with elallas/get-case, elallas/list-cases, elallas/update-case-status, and elallas/get-audit-log (via lw_site_manager_register_abilities / lw_site_manager_register_categories, with a fallback direct registration on wp_abilities_api_init). So agents/automation can read and drive cases through Site Manager without touching the tables. Verified at SiteManager/Integration.php:34-39. See lw-site-manager-overview and wp-abilities-api.

WooCommerce logging

The plugin writes to WooCommerce -> Status -> Logs with source elallas-for-woo. warning/error are always written; notice/info/debug require the "Debug logging" option. Context is scrubbed for common PII keys, so integration code should log only identifiers (case_id, order_id, display order_number, status, exception class), never email, IP, user-agent, names, notes or bank-account data.

Critical rules

  • Never edit the plugin. Consume elallas_* hooks; request missing extension points upstream. (LW-family rule.)
  • Detect with defined('ELALLAS_FOR_WOO_VERSION') and degrade gracefully when absent.
  • Customer-entered order numbers are display numbers. Support custom order numbering through elallas_resolve_order_number; never absint() the public form value.
  • elallas_case_status_changed has 4 args in 1.0.12+ — register accepted args as 4 if you need the customer-visible status note.
  • $case_id is a custom-table row ID, not a post. Use the plugin's data layer / tables, not get_post_meta.
  • elallas_is_order_eligible is the final gate — compose with $eligible && your_condition to narrow; returning bare true can re-enable orders the built-in checks (status, open case, ownership, expired-blocked) denied.
  • Order meta (_lw_elallas_*) is read-only for you — the plugin owns those writes; read to discover cases, don't set them.
  • Withdrawal-exception product/term meta is configuration, not a denial decision — it flags case items as excepted; final decision remains in the case workflow.
  • HPOS-safe: work with the passed \WC_Order via getters, never post meta.
  • Multilingual strings are runtime-translated — do not read/store raw option strings for customer output and do not duplicate them as WPML admin-texts.
  • Case statuses are the CaseStatus enum (ten values) — don't invent statuses; validate with CaseStatus::is_valid().
  • B2B detection is a heuristic (company/VAT presence) the merchant overrides per case — treat elallas_is_order_b2b as advisory, not authoritative legal classification.

Common mistakes

// WRONG — treating the case id as a post
$note = get_post_meta( $case_id, 'note', true );   // case_id is a wp_lw_elallas_cases row id, not a post

// WRONG — re-allowing everything (ignores built-in eligibility)
add_filter( 'elallas_is_order_eligible', '__return_true' );   // bypasses status/deadline/ownership checks

// RIGHT — only narrow
add_filter( 'elallas_is_order_eligible', fn( $ok, $order ) => $ok && my_extra_check( $order ), 10, 2 );

// WRONG — writing the plugin's order meta yourself
$order->update_meta_data( '_lw_elallas_has_case', 'yes' );   // the plugin owns this write

// WRONG — breaking stores with custom/sequential order numbers
$order_id = absint( $_POST['order_number'] ?? 0 );            // customer sees display number, not always WC ID

// RIGHT — let Elállás or your filter resolve the display number
add_filter( 'elallas_resolve_order_number', 'my_resolve_display_order_number', 10, 2 );

Cross-references

  • wc-hpos-compatibility — the plugin is HPOS-safe; keep your integration HPOS-safe too.
  • wc-sequential-order-numbers-pro — display order numbers must resolve before the withdrawal flow can identify an order.
  • wc-order-lifecycle-and-items — for reacting to the underlying WooCommerce order/refund side.
  • lw-site-manager-overview / wp-abilities-api — the elallas/* abilities it exposes.
  • wpml-string-translation / wpml-config — understand the runtime string registration and the intentional wpml-config.xml scope.
  • See reference.md for the full hook table, the 4-table schema, the order meta keys, and the status/options enums.

What this skill does NOT cover

  • The plugin's admin UI / case workflow as an end user — this is a developer-integration skill.
  • The legal/compliance interpretation of Directive 2023/2673 or 415/2025 Korm. rendelet — that's the plugin's domain, not this skill's.
  • Editing the plugin's internals — out of scope by design (consume hooks).
  • The withdrawal-form Gutenberg block internals (blocks/withdrawal-form) — beyond noting it exists.

References

What ships with it: 1 file

10.7 KB alongside SKILL.md

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.