Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions includes/class-splash-wordpress-plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ public function __construct($file = '', $version = SPLASH_SYNC_VERSION)
Splash\Local\Objects\ThirdParty::registerHooks();
Splash\Local\Objects\Product::registerHooks();
Splash\Local\Objects\Order::registerHooks();
Splash\Local\Objects\CreditNote::registerHooks();

//====================================================================//
// Handle User Messages
Expand Down
160 changes: 160 additions & 0 deletions src/Objects/CreditNote.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<?php

/*
* This file is part of SplashSync Project.
*
* Copyright (C) Splash Sync <www.splashsync.com>
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Splash\Local\Objects;

use Splash\Models\AbstractObject;
use Splash\Models\Objects;
use WC_Order_Refund;

/**
* WooCommerce Credit Note Object
*
* Unlike Invoice, which is a virtual read-only view of an Order, a Credit Note is
* backed by a real WooCommerce entity: the `shop_order_refund` post type, handled
* by the WC_Order_Refund class.
*
* This matters for the Dolibarr connector, whose CreditNote object carries a
* `fk_facture_source` pointing back at the invoice being credited. WooCommerce has
* the exact same link natively, as the refund's `post_parent`, so the two sides can
* be mapped without inventing anything.
*
* SIGN CONVENTION
* The Dolibarr connector needs a dedicated `Core\CreditModeTrait` to invert every
* price, because a Dolibarr credit note stores positive amounts. WooCommerce does
* not: `get_total()` already returns a negative value (`get_amount()` is the
* positive one). No inversion trait is needed here — but do not mix the two getters.
*
* SCOPE OF THIS OBJECT
* Read-only for now, exactly like Invoice. Creating a refund from a remote server
* is a money-moving operation — it can trigger a gateway refund — so it is left out
* until the write path has been designed explicitly.
*/
class CreditNote extends AbstractObject
{
//====================================================================//
// Splash Php Core Traits
//====================================================================//

use Objects\IntelParserTrait;
use Objects\SimpleFieldsTrait;
use Objects\GenericFieldsTrait;
use Objects\PricesTrait;
use Objects\ListsTrait;

//====================================================================//
// Core Fields
//====================================================================//

use Core\WooCommerceObjectTrait; // Trigger WooCommerce Module Activation

//====================================================================//
// WooCommerce Credit Note Fields
//====================================================================//

use CreditNote\CRUDTrait; // Objects CRUD
use CreditNote\ObjectListTrait; // Objects Listing
use CreditNote\HooksTrait; // WordPress Hooks
use CreditNote\CoreTrait; // Credit Note Core Infos
use CreditNote\ItemsTrait; // Credit Note Items List
use CreditNote\TotalsTrait; // Credit Note Totals

//====================================================================//
// Object Definition Parameters
//====================================================================//

/**
* Object Name (Translated by Module)
*
* {@inheritdoc}
*/
protected static string $name = "Credit Note";

/**
* Object Description (Translated by Module)
*
* {@inheritdoc}
*/
protected static string $description = "WooCommerce Order Refund";

/**
* Object Icon (FontAwesome or Glyph ico tag)
*
* {@inheritdoc}
*/
protected static string $ico = "fa fa-reply";

//====================================================================//
// Object Synchronization Limitations
//
// This Flags are Used by Splash Server to Prevent Unexpected Operations on Remote Server
//====================================================================//

/**
* {@inheritdoc}
*/
protected static bool $allowPushCreated = false;

/**
* {@inheritdoc}
*/
protected static bool $allowPushUpdated = false;

/**
* {@inheritdoc}
*/
protected static bool $allowPushDeleted = false;

/**
* {@inheritdoc}
*/
protected static bool $enablePushCreated = false;

/**
* {@inheritdoc}
*/
protected static bool $enablePushUpdated = false;

/**
* {@inheritdoc}
*/
protected static bool $enablePushDeleted = false;

//====================================================================//
// General Class Variables
//====================================================================//

/**
* @var WC_Order_Refund
*/
protected object $object;

/**
* @var string
*/
protected string $postType = "shop_order_refund";

//====================================================================//
// Class Constructor
//====================================================================//

/**
* Class Constructor
*/
public function __construct()
{
self::setGenericMethodsFormat("snake_case");
}
}
141 changes: 141 additions & 0 deletions src/Objects/CreditNote/CRUDTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php

/*
* This file is part of SplashSync Project.
*
* Copyright (C) Splash Sync <www.splashsync.com>
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Splash\Local\Objects\CreditNote;

use Splash\Core\SplashCore as Splash;
use Splash\Local\Core\PrivacyManager;
use WC_Order;
use WC_Order_Refund;

/**
* WooCommerce Credit Note CRUD Functions
*/
trait CRUDTrait
{
/**
* Load Request Object
*
* @param string $postId Object id
*
* @return null|WC_Order_Refund
*/
public function load(string $postId): ?WC_Order_Refund
{
//====================================================================//
// Stack Trace
Splash::log()->trace();
//====================================================================//
// Init Object
// wc_get_order() returns the right class for any order-like post type,
// so a refund id gives back a WC_Order_Refund.
$wcRefund = wc_get_order((int) $postId);
if (!$wcRefund instanceof WC_Order_Refund) {
return Splash::log()->errNull(
"Unable to load ".$this->postType." (".$postId.")."
);
}
//====================================================================//
// Check Parent Order Not Anonymized
// A refund carries no personal data of its own: it inherits the customer
// from its parent order, so the parent is what has to be checked.
$parent = $this->getParentOrder($wcRefund);
if ($parent && PrivacyManager::isAnonymize($parent)) {
return Splash::log()->errNull("Reading Anonymized Orders is Forbidden");
}

return $wcRefund;
}

/**
* Create Request Object
*
* Refunds are read-only: creating one is a money-moving operation that may
* trigger a gateway refund, so it is deliberately not exposed.
*
* @return null|WC_Order_Refund
*/
public function create(): ?WC_Order_Refund
{
return Splash::log()->errNull(
"Creating WooCommerce Refunds from Splash is not allowed."
);
}

/**
* Update Request Object
*
* @param bool $needed Is This Update Needed
*
* @return null|string Object ID
*/
public function update(bool $needed): ?string
{
//====================================================================//
// Stack Trace
Splash::log()->trace();
//====================================================================//
// Object is Read-Only: nothing is ever written back.
if ($needed) {
Splash::log()->war("WooCommerce Refunds are Read-Only. Changes were ignored.");
}

return $this->getObjectIdentifier();
}

/**
* Delete Request Object
*
* @param string $postId Object id
*
* @return bool
*/
public function delete(string $postId): bool
{
return Splash::log()->warTrace(
"Deleting WooCommerce Refunds from Splash is not allowed. ID ".$postId
);
}

/**
* {@inheritdoc}
*/
public function getObjectIdentifier(): ?string
{
$refundId = $this->object->get_id();

return empty($refundId) ? null : (string) $refundId;
}

/**
* Get the Order this Refund belongs to
*
* This is the WooCommerce counterpart of Dolibarr's `fk_facture_source`.
*
* @param WC_Order_Refund $wcRefund
*
* @return null|WC_Order
*/
protected function getParentOrder(WC_Order_Refund $wcRefund): ?WC_Order
{
$parentId = $wcRefund->get_parent_id();
if (empty($parentId)) {
return null;
}
$parent = wc_get_order($parentId);

return ($parent instanceof WC_Order) ? $parent : null;
}
}
Loading