# Inventario

> Lleve existencias de sus productos: cada factura saca lo que vende, y usted ve lo que hay en cada almacén, el kárdex y sus ajustes.

Un producto con `track_stock: true` lleva existencias. Cada factura que lo vende (con su `product`, o con su SKU o código de barras como `NoIdentificacion`) saca lo que vende del almacén de su sucursal en el momento en que se timbra, y una factura cancelada lo regresa. Es el mismo Inventario de la app: lo que haga ahí (compras, traspasos, conteos) se ve aquí, y al revés.

## Almacenes

El emisor tiene un almacén por lugar desde donde factura: el de la Matriz y uno por cada [sucursal](https://fiscalisto.com/docs/api/sucursales), que se crean solos.

```bash tab="cURL"
curl https://api.fiscalisto.com/v1/warehouses \
  -H "Authorization: Bearer $FISCALISTO_API_KEY"
```

```ts tab="TypeScript"
import { Fiscalisto } from "fiscalisto";

// La llave viene de FISCALISTO_API_KEY.
const fiscalisto = new Fiscalisto();

const { data } = await fiscalisto.warehouses.list();
```

```python tab="Python"
from fiscalisto import Fiscalisto

# La llave viene de FISCALISTO_API_KEY.
fiscalisto = Fiscalisto()

data = fiscalisto.warehouses.list()["data"]
```

```php tab="PHP"
<?php

use Fiscalisto\Fiscalisto;

// La llave viene de FISCALISTO_API_KEY.
$fiscalisto = new Fiscalisto();

$data = $fiscalisto->warehouses->list()['data'];
```

```go tab="Go"
package main

import (
	"context"
	"fmt"
	"log"

	fiscalisto "fiscalisto.com/go"
)

func main() {
	// La llave viene de FISCALISTO_API_KEY.
	client, err := fiscalisto.NewClient("")
	if err != nil {
		log.Fatal(err)
	}
	ctx := context.Background()

	warehouseList, err := client.Warehouses.List(ctx, nil)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%+v\n", *warehouseList)
}
```

```java tab="Java"
import com.fiscalisto.FiscalistoClient;

// La llave viene de FISCALISTO_API_KEY.
var fiscalisto = new FiscalistoClient();

var warehouseList = fiscalisto.warehouses().list();
System.out.println(warehouseList);
```

```csharp tab="C#"
using Fiscalisto;

// La llave viene de FISCALISTO_API_KEY.
var fiscalisto = new FiscalistoClient();

var warehouseList = await fiscalisto.Warehouses.ListAsync();
```

Una factura vende del almacén de su sucursal (`branch`), o del de la Matriz sin ella. Para que salga de otro, mande `warehouse` (`whs_…`) en la factura.

## Las existencias iniciales

Marque el producto con `track_stock: true` (al crearlo o con `POST /v1/products/{id}`) y meta lo que tiene con un ajuste:

```bash tab="cURL"
curl https://api.fiscalisto.com/v1/stock_adjustments \
  -H "Authorization: Bearer $FISCALISTO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "initial",
    "note": "Inventario de apertura",
    "lines": [{ "product": "prd_OufpKqnrvx9p2", "quantity": 50, "unit_cost": 90 }]
  }'
```

```ts tab="TypeScript"
import { Fiscalisto } from "fiscalisto";

// La llave viene de FISCALISTO_API_KEY.
const fiscalisto = new Fiscalisto();

const stockAdjustment = await fiscalisto.stockAdjustments.create({
  reason: "initial",
  note: "Inventario de apertura",
  lines: [
    {
      product: "prd_OufpKqnrvx9p2",
      quantity: 50,
      unit_cost: 90,
    },
  ],
});
```

```python tab="Python"
from fiscalisto import Fiscalisto

# La llave viene de FISCALISTO_API_KEY.
fiscalisto = Fiscalisto()

stock_adjustment = fiscalisto.stock_adjustments.create({
    "reason": "initial",
    "note": "Inventario de apertura",
    "lines": [
        {
            "product": "prd_OufpKqnrvx9p2",
            "quantity": 50,
            "unit_cost": 90,
        },
    ],
})
```

```php tab="PHP"
<?php

use Fiscalisto\Fiscalisto;

// La llave viene de FISCALISTO_API_KEY.
$fiscalisto = new Fiscalisto();

$stockAdjustment = $fiscalisto->stockAdjustments->create([
    'reason' => 'initial',
    'note' => 'Inventario de apertura',
    'lines' => [
        [
            'product' => 'prd_OufpKqnrvx9p2',
            'quantity' => 50,
            'unit_cost' => 90,
        ],
    ],
]);
```

```go tab="Go"
package main

import (
	"context"
	"fmt"
	"log"

	fiscalisto "fiscalisto.com/go"
)

func main() {
	// La llave viene de FISCALISTO_API_KEY.
	client, err := fiscalisto.NewClient("")
	if err != nil {
		log.Fatal(err)
	}
	ctx := context.Background()

	stockAdjustment, err := client.StockAdjustments.Create(ctx, &fiscalisto.CreateStockAdjustmentParams{
		Reason: "initial",
		Note:   fiscalisto.String("Inventario de apertura"),
		Lines: []fiscalisto.CreateStockAdjustmentParamsLine{
			{
				Product:  "prd_OufpKqnrvx9p2",
				Quantity: 50,
				UnitCost: fiscalisto.Float64(90),
			},
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(stockAdjustment.ID)
}
```

```java tab="Java"
import com.fiscalisto.FiscalistoClient;
import com.fiscalisto.model.CreateStockAdjustmentParams;
import com.fiscalisto.model.CreateStockAdjustmentParamsLine;
import java.util.List;

// La llave viene de FISCALISTO_API_KEY.
var fiscalisto = new FiscalistoClient();

var stockAdjustment = fiscalisto.stockAdjustments().create(new CreateStockAdjustmentParams()
        .setReason("initial")
        .setNote("Inventario de apertura")
        .setLines(List.of(
                new CreateStockAdjustmentParamsLine()
                        .setProduct("prd_OufpKqnrvx9p2")
                        .setQuantity(50)
                        .setUnitCost(90)
        )));
System.out.println(stockAdjustment.getId());
```

```csharp tab="C#"
using Fiscalisto;

// La llave viene de FISCALISTO_API_KEY.
var fiscalisto = new FiscalistoClient();

var stockAdjustment = await fiscalisto.StockAdjustments.CreateAsync(new CreateStockAdjustmentParams
{
    Reason = "initial",
    Note = "Inventario de apertura",
    Lines = new()
    {
        new()
        {
            Product = "prd_OufpKqnrvx9p2",
            Quantity = 50,
            UnitCost = 90,
        },
    },
});
```

Sin `warehouse` va al almacén de la Matriz. Una cantidad positiva entra y una negativa sale; las entradas valen su `unit_cost` (pesos sin IVA, o el costo promedio de hoy sin él) y las salidas el costo del emisor (promedio o PEPS, el que eligió en la app). El motivo (`reason`) es `initial`, `surplus`, `shrinkage` (merma), `theft`, `damage`, `expiration`, `internal_use`, `gift`, `count` u `other`. Un producto con lotes o números de serie pide `lot` en cada línea.

Si el emisor eligió en la app no vender sin existencias, una factura que pide más de lo que hay se rechaza antes de timbrarse, y el mensaje dice de qué producto. Lo que Inventario no puede hacer en un ajuste (un lote que no es de ese producto, otro ajuste del mismo almacén en ese momento) contesta `inventory_refused`.

## Lo que hay

```bash tab="cURL"
curl https://api.fiscalisto.com/v1/products/prd_OufpKqnrvx9p2/stock \
  -H "Authorization: Bearer $FISCALISTO_API_KEY"
```

```ts tab="TypeScript"
import { Fiscalisto } from "fiscalisto";

// La llave viene de FISCALISTO_API_KEY.
const fiscalisto = new Fiscalisto();

const { data } = await fiscalisto.products.stock("prd_OufpKqnrvx9p2");
```

```python tab="Python"
from fiscalisto import Fiscalisto

# La llave viene de FISCALISTO_API_KEY.
fiscalisto = Fiscalisto()

data = fiscalisto.products.stock("prd_OufpKqnrvx9p2")["data"]
```

```php tab="PHP"
<?php

use Fiscalisto\Fiscalisto;

// La llave viene de FISCALISTO_API_KEY.
$fiscalisto = new Fiscalisto();

$data = $fiscalisto->products->stock('prd_OufpKqnrvx9p2')['data'];
```

```go tab="Go"
package main

import (
	"context"
	"fmt"
	"log"

	fiscalisto "fiscalisto.com/go"
)

func main() {
	// La llave viene de FISCALISTO_API_KEY.
	client, err := fiscalisto.NewClient("")
	if err != nil {
		log.Fatal(err)
	}
	ctx := context.Background()

	stockLevelList, err := client.Products.Stock(ctx, "prd_OufpKqnrvx9p2")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%+v\n", *stockLevelList)
}
```

```java tab="Java"
import com.fiscalisto.FiscalistoClient;

// La llave viene de FISCALISTO_API_KEY.
var fiscalisto = new FiscalistoClient();

var stockLevelList = fiscalisto.products().stock("prd_OufpKqnrvx9p2");
System.out.println(stockLevelList);
```

```csharp tab="C#"
using Fiscalisto;

// La llave viene de FISCALISTO_API_KEY.
var fiscalisto = new FiscalistoClient();

var stockLevelList = await fiscalisto.Products.StockAsync("prd_OufpKqnrvx9p2");
```

Una fila por almacén: `on_hand` (lo que hay), `reserved` (lo apartado por cotizaciones aceptadas), `available` (lo que se puede vender), `value` y `average_cost`. `GET /v1/warehouses/{id}/stock` da lo mismo por producto dentro de un almacén, de 100 en 100.

## El kárdex

`GET /v1/stock_movements` lista cada entrada y salida, la más reciente primero: `type` dice qué fue (`sale`, `purchase`, `adjustment`, `transfer_out`, `reversal`…) y `source` qué la causó (el UUID de la factura, el `adj_…` del ajuste). Filtre por `product`, `warehouse`, `type` y por día con `date_gte` y `date_lte`, en hora de la Ciudad de México: una venta a las 11:30 pm del 31 es del 31.
