# Frisbo SDK v1

The full API documentation can be found on developers.frisbo.ro.

## Example of usage

### Client selection

First you should select a client, based on your own environment and current dependencies.

Current implemented clients:

- Frisbo\FrisboSdk\Clients\V1\FrisboGuzzle5Client (support for legacy Guzzle 5)  
- Frisbo\FrisboSdk\Clients\V1\FrisboGuzzleClient (support for modern Guzzle >= 6)  

You can implement your own client easily by extending the FrisboV1Client class.

For the following examples, we will use FrisboGuzzle5Client.

### Using the client

```php
use Frisbo\FrisboSdk\Clients\V1\FrisboGuzzle5Client;

// use the client by providing the username and password for your account and a Cache to store the token in
// by default we use the FileCache, but be sure to provide it with a writable/readable path
$frisboClient = new FrisboGuzzle5Client(['username' => $username, 'password' => $password], new FrisboFileCache());

// get the list of organizations your account has access to
$organizations = $frisboClient->getOrganizations();

// get the selling channels available for the first organization you have access to
$sellingChannels = $frisboClient->getOrganizationChannels($organizations[0]->organization_id);
```

### Sending a product

```php
...
use Frisbo\FrisboSdk\Models\Product;

...

$frisboProduct = new Product();
$frisboProduct->name = 'NAME OF PRODUCT'; 
$frisboProduct->sku = 'SKUOFPRODUCT';
$frisboProduct->upc = 'UPC barcode here';
$frisboProduct->ean = 'EAN barcode here - same as upc if not exists';
$frisboProduct->external_code = '2131241414 - internal product code of your platform here';
// also add dimensions of a product
$frisboProduct->dimensions = new ProductDimensions();
$frisboProduct->dimensions->height = 0.1; // height in cm
$frisboProduct->dimensions->width = 0.1; // width in cm
$frisboProduct->dimensions->length = 0.1; // length in cm
$frisboProduct->dimensions->weight = 0.1; // weight in kg

$createdProductInFrisbo = $frisboClient->sendProduct($frisboOrganizationId, $frisboProduct);

// now the created product will have an id if it was succesfully sent to Frisbo, otherwise will throw an error
echo $createdProductInFrisbo->product_id;
```


### Getting stocks for a product using filters

There are two methods of getting the stock from Frisbo.

Method 1 - will return the automatically computed available stock for the selected selling channel (aggregating from multiple warehouses)

```php

...
use Frisbo\FrisboSdk\Models\Filters\Filter;

// getting only the stocks that have been modified from 2021-01-01
$frisboClient->getStocksByFilter(
  $frisboOrganizationId, 
  $frisboChannelId, 
  new Filter('updated_at', '2021-01-01', 'greater_than')
);

// getting a single stock for an sku
$frisboClient->getStocksByFilter(
  $frisboOrganizationId, 
  $frisboChannelId, 
  new Filter('sku', 'SKUYOUWANTTOSEARCH')
);

// getting stocks for multiple skus at once
$storages = $frisboClient->getStocksByFilter(
  $frisboOrganizationId, 
  $frisboChannelId, 
  new Filter('sku', 'SKU1,SKU2', 'in')
);

echo 'Available stock for ' . $storages[0]->product->sku . ' is ' . $storages[0]->available_stock;

```

Method 2 - not recommended if you use multiple warehouses and stock locations since you need to aggregate the results yourself

Also, you cannot filter for stocks that have been modified after a certain date.

```php

...
use Frisbo\FrisboSdk\Models\Filters\Filter;

// getting a single product by sku
$products = $frisboClient->getProductsByFilter(
  $frisboOrganizationId, 
  new Filter('sku', 'SKUYOUWANTTOSEARCH'));

// getting multiple products at once by sku
$products = $frisboClient->getProductsByFilter(
  $frisboOrganizationId, 
  new Filter('sku', 'SKU1,SKU2', 'in')
);

echo 'Available stock for '. $products[0]->sku  .' in location ' . $products[0]->storage[0]->warehouse_id . ' is ' . $products[0]->storage[0]->available_stock;
```

### Sending an order to Frisbo

Now that your products are synced, you can start sending orders.

```php

use Frisbo\FrisboSdk\Models\Order;

...

// we can use the convenience method fromObject to create a Frisbo Order that the client can use
$frisboOrderArray = [
    'order_reference' => 'internalOrderId',
    'ordered_date' => '2021-12-23 23:59:59', // datetime when the order entered the store (UTC)
    'channel_id' => $frisboChannelId,
    'warehouse_id' => -1,
    'notes' => 'order notes here',
    'organization_id' => $frisboOrganizationId,
    'notification_url' => 'https://api.yourownndomain.com/frisbo/internalOrderId', // we will send POST notifications to this url when order changes status
    'discount' => 20, // global discount on order
    'transport_tax'=> 20, // transport tax for the order
    'cash_on_delivery' => true, // if cash_on_delivery is true
    // shipping
    'shipping_customer' => [
        'email' => 'email@email.com',
        'first_name' => 'firstName',
        'last_name' => 'lastName',
        'phone' => '032141241',
        'vat_registration_number' => 'RO211231', // if b2b, otherwise null
        'trade_register_registration_number' => 'J12/1312/21', // if b2b, otherwise null
    ],
    'shipping_address' => [
        'street' => 'Str. Ion Ratiu 28A',
        'city' => 'Constanta',
        'county' => 'Constanta',
        'country' => 'Romania',
        'zip' => '900532',
    ],
    // billing
    'billing_customer' => [
        'email' => 'email@email.com',
        'first_name' => 'firstName',
        'last_name' => 'lastName',
        'phone' => '032141241',
        'vat_registration_number' => 'RO211231', // if b2b, otherwise null
        'trade_register_registration_number' => 'J12/1312/21', // if b2b, otherwise null
    ],
    'billing_address' => [
        'street' => 'Str. Ion Ratiu 28A',
        'city' => 'Constanta',
        'county' => 'Constanta',
        'country' => 'Romania',
        'zip' => '900532',
    ],
    'products' => [
      [
          'sku' => 'SKU1',
          'name' => 'NAME ON ORDER',
          'vat' => 19,
          'price_with_vat' => 100,
          'quantity' => 1,
      ],
      [
          'is_virtual' => true,
          'name' => 'EXTRA PACKING SERVICE',
          'vat' => 19,
          'price_with_vat' => 20,
          'quantity' => 1,
      ],
      [
          'product_id' => 213131, // frisbo product id
          'name' => 'NAME ON ORDER',
          'vat' => 19,
          'price_with_vat' => 100,
          'quantity' => 1,
      ],
    ]
];

$frisboOrder = FrisboOrder::fromObject((object) $frisboOrderArray);
$createdOrder = $frisboClient->sendOrder($frisboOrganizationId, $frisboOrder);

// if everything is ok, you should now receive the created order that has a Frisbo order id

echo $createdOrder->order_id;

// we recommend caching the order id when first sending it to Frisbo

```

### Getting orders from Frisbo

```php

// getting orders by their references
$orders = $frisboClient->getOrdersByFilter(
  $frisboOrganizationId, 
  new Filter('order_reference', 'internalOrderId')
);

// getting multiple orders by their Frisbo ids
$orders = $frisboClient->getOrdersByFilter(
  $frisboOrganizationId, 
  new Filter('order_id', 'frisboOrderId1,frisboOrderId2', 'in')
);

// getting orders created from a certain date
$orders = $frisboClient->getOrdersByFilter(
  $frisboOrganizationId, 
  new Filter('created_at', '2021-12-01', 'greater_than')
);

// getting orders created in December
$orders = $frisboClient->getOrdersByFilter(
  $frisboOrganizationId, 
  new Filter('created_at', '2021-12-01', 'greater_than'), 
  new Filter('created_at', '2022-01-01', 'less_than')
);

echo 'Status for the order ' . $orders[0]->order_reference . ' is ' . $orders[0]->fulfillment->status;
```

### Canceling an order in Frisbo

```php

// when you have the id cached already
$frisboOrder = new Order();
$frisboOrder->order_id = $frisboOrderId;

$canceledOrder = $frisboClient->cancelOrder($frisboOrganizationId, $frisboOrder);

// when you need the id first
$orders = $frisboClient->getOrdersByFilter(
  $frisboOrganizationId, 
  new Filter('order_reference', 'internalOrderId')
);
$canceledOrder = $frisboClient->cancelOrder($frisboOrganizationId, $orders[0]);
```
