如何创建或更新具有审计历史记录的复杂Eloquent模型自动保存

I am building an app which imports data from various eCommerce platforms, including Shopify. That data can change when an admin updates an order. The app must always have an up-to-date record, as well as audit history to see what changed and when. I'm using the Laravel Auditing package for recording changes.

Ideally, my code should only be responsible for:

  1. Populating the PHP model objects with data (order, addresses, items)
  2. Relating the models to each other (add items/addresses to order)

Then I would like Eloquent to handle the heavy lifting of:

  1. Checking for an existing record for any of those models
  2. Inserting a new one if not, or updating it if yes
  3. Saving audit history of what changed

For example, if the order itself didn't change, but the address did, when I call $order->save() it should update the address, and save audit history.

One option could be to check if the Address or OrderItem exists in the DB before populating the model with data. That's not ideal because:

  1. The class populating the model should only be responsible for filling it with data: it shouldn't care whether the record exists already or not, as that would break the Single Responsibility Principle.
  2. The class populating the Address models would need to know what Order model the address is for. This too violates SRP.
  3. I would also like to avoid having separate functions for createNewOrder() and updateExistingOrder(), to avoid code duplication.

Here's what I have so far:

When the app sees an order for the first time, it populates models, then INSERTs records for these entities like so:

$order = SalesOrder::firstOrNew([
    'store_id' => $orderData['store_id'],
    'external_id' => $orderData['external_id']
]);

$order->save();
$order->salesOrderAddresses()->save($billingAddress);

if(@$shippingAddress) {
    $order->salesOrderAddresses()->save($shippingAddress);
}

$order->salesOrderItems()->saveMany($items);

I have audit history working for the order itself. That part works fine, but it would be great if I could build up the entire order model first, then call a single save() make Eloquent intelligently save any changes to the database.

In the SalesOrder class, I have these relations:

public function salesOrderAddresses() {
    return $this->hasMany(SalesOrderAddress::class,'order_id');
}
public function salesOrderItems() {
    return $this->hasMany(SalesOrderItem::class,'order_id');
}

The hierarchy is like this:

SalesOrder = [
    Addresses [
        Address (billing),
        Address (shipping)
    ],
    Items = [
        [
            sku: abc,
            qty: 123
        ],
        [
            sku: xyz,
            qty: 321
        ]
    ]
]

Anyway, I'm probably approaching this entirely the wrong way. Hopefully some seasoned Eloquent/Laravel dev out there can suggest a better way of handling this.