Erreur : bad operand type for abs(): sur creation de Sales Order

Bonsoir,

Sur une première création de Sales Order par REST API (sur une installation qui fonctionne déjà en direct), j’ai une erreur têtue

L’appel API :

URL = string(52) "https://-----.dokos.cloud/api/resource/Sales Order" method POST / action resource/Sales Order ok
data
Array
(
    [item] => Array
        (
            [name] => Le ----
            [item_code] => Le ----
            [item_name] => Le -----
            [delivery_date] => 2022-11-01
            [qty] => 1
            [item_booking] => STO-BOOK-2022-00043
            [item_booking_start] => 2022-11-01 17:00:00
            [item_booking_end] => 2022-11-01 21:00:00
            [item_group] => Espaces ---
            [doctype] => Item Booking
        )

    [customer_name] => Jean (test)
    [address] => Adresse test-Facturation
    [customer] => Jean (test)
)

Le retour (erreur 500 avec un beau retour d’erreur Python dans le retour API …)

    [0] => Traceback (most recent call last):
  File "/home/dokos/hetz2/apps/frappe/frappe/app.py", line 68, in application
    response = frappe.api.handle()
  File "/home/dokos/hetz2/apps/frappe/frappe/api.py", line 139, in handle
    doc = frappe.get_doc(data).insert()
  File "/home/dokos/hetz2/apps/frappe/frappe/model/document.py", line 241, in insert
    self.run_before_save_methods()
  File "/home/dokos/hetz2/apps/frappe/frappe/model/document.py", line 998, in run_before_save_methods
    self.run_method("validate")
  File "/home/dokos/hetz2/apps/frappe/frappe/model/document.py", line 890, in run_method
    out = Document.hook(fn)(self, *args, **kwargs)
  File "/home/dokos/hetz2/apps/frappe/frappe/model/document.py", line 1190, in composer
    return composed(self, method, *args, **kwargs)
  File "/home/dokos/hetz2/apps/frappe/frappe/model/document.py", line 1173, in runner
    add_to_return_value(self, fn(self, *args, **kwargs))
  File "/home/dokos/hetz2/apps/frappe/frappe/model/document.py", line 884, in 
    fn = lambda self, *args, **kwargs: getattr(self, method)(*args, **kwargs)
  File "/home/dokos/hetz2/apps/erpnext/erpnext/selling/doctype/sales_order/sales_order.py", line 36, in validate
    super(SalesOrder, self).validate()
  File "/home/dokos/hetz2/apps/erpnext/erpnext/controllers/selling_controller.py", line 31, in validate
    super(SellingController, self).validate()
  File "/home/dokos/hetz2/apps/erpnext/erpnext/controllers/stock_controller.py", line 22, in validate
    super(StockController, self).validate()
  File "/home/dokos/hetz2/apps/erpnext/erpnext/controllers/accounts_controller.py", line 108, in validate
    self.set_total_in_words()
  File "/home/dokos/hetz2/apps/erpnext/erpnext/controllers/selling_controller.py", line 120, in set_total_in_words
    amount = abs(self.grand_total if self.is_rounded_total_disabled() else self.rounded_total)
TypeError: bad operand type for abs(): 'NoneType'

J’ai essayé de remplir tous les champs possibles

'base_total'	=> 160.00,
			'base_net_total'	=> 133.33,
			'base_total_taxes_and_charges'=> 26.66,
			'total_taxes_and_charges'	=> 26.66,
			'base_rounded_total'	=> 160,
			'grand_total'	=> 160.00,			
			'total'	=> 160.00,
			'base_grand_total'	=> 160.00,

sans changement.

Avez vous une idée ? Je ne trouve rien dans la documentation sur les champs nécessaires à la création d’un Sales Order

Merci

Bonjour @Malaiac,

La liste d’articles n’est pas correcte, du coup l’article ne peut pas être ajouté à la commande et la validation de celle-ci tombe en erreur.
En l’occurrence, le champ name donne l’identifiant d’une ligne de commande qui existerait déjà, ce qui n’est pas le cas. Et la valeur du champ doctype n’est pas correcte: ici le doctype correspondant aux articles est Sales Order Item.

Voici un exemple de données minimum nécessaires pour créer une commande via l’API Rest:

{
    "customer": "Aceline Lacasse",
    "items": [
        {
            "item_code": "Coworking mensuel",
            "delivery_date": "2022-01-27",
            "qty": 1
        }
    ]
}

Bonne journée

Merci de cette réponse

J’ai bien un code 200 sur

    [items] => Array
        (
            [0] => Array
                (
                    [item_code] => Le ---- ( nom du lieu)
                    [delivery_date] => 2022-11-01
                    [qty] => 1
                )

        )

    [customer] => Jean (test)

Mais je voudrais pouvoir créer une commande à partir d’une Réservation plutot que d’un Lieu

La commande n’est pas liée, me semble-t-il, à un Lieu, mais à une Réservation ( Lieu + Date + UOM + quantité)
sur cette Réservation, c’est une demi journée qui démarre à 17h00, ce qui n’est pas connu dans la commande créée
Et la réservation déjà existante n’est pas liée à la commande.

Logiquement, je voudrais envoyer :

 [items] => Array
        (
            [0] => Array
                (
                    [item_code] => STO-BOOK-2022-00043 // code de la réservation
                    [delivery_date] => 2022-11-01
                    [qty] => 1
                )

        )
    [customer] => Jean (test)

et créer ainsi une commande pour Jean (test) incluant la Réservation existante.
Cet appel renvoie un 417


Autre exemple, sur un Lieu avec deux UOM (Journée 60 € et Demi journée 40 €)
Booking bien créé :
[name] => STO-BOOK-2022-00053
…
[starts_on] => 2022-11-01 14:00:00
[ends_on] => 2022-11-02 21:00:00
(soit 1 jour et demi)

Logiquement (de mon point de vue), je voudrais envoyer :

(
    [items] => Array
        (
            [0] => Array
                (
                    [item_code] => STO-BOOK-2022-00053
                    [delivery_date] => 2022-11-01
                    [qty] => 1
                )

        )

    [customer] => Jean (test)
)

et créer une commande contenant cette réservation
RĂ©sultat : 417

En revanche si j’envoie :

(
    [items] => Array
        (
            [0] => Array
                (
                    [item_code] => La Grande ----
                    [delivery_date] => 2022-11-01
                    [qty] => 1
                )

        )

    [customer] => Jean (test)
)

j’ai bien un code 200 et une création de commande, qui a (arbitrairement ?) compté une Demi Journée soit 40 €

si j’envoie 3 en quantité

(
    [items] => Array
        (
            [0] => Array
                (
                    [item_code] => La Grande ----
                    [delivery_date] => 2022-11-01
                    [qty] => 3
                )

        )

    [customer] => Jean (test)
)

j’ai bien un code 200 et une création de commande, qui a compté trois Demi Journée soit 120 €

Dans tous les cas, les commandes n’ont pas de lien établi avec les réservations

Je suppose que c’est une erreur de conception de ma part dans les relations entre Réservations et Commande. Sur le dashboard, je constate cependant que les Réservations sont pour la plupart liées à des Commandes, et j’aurais aimé pouvoir dupliquer ce fonctionnement via l’API.

Merci de votre aide

Bonjour @Malaiac,

Les commandes et les réservations sont deux objets différents:

  • Une commande peut ĂŞtre crĂ©Ă©e indĂ©pendemment d’une rĂ©servation
  • Une rĂ©servation peut ĂŞtre crĂ©Ă©e indĂ©pendemment d’une commande

Il faut donc commencer par créer la réservation, puis une commande en liant la réservation à la ligne de commande correspondante.

En ce qui concerne les unités de mesure, c’est à toi de passer l’unité de mesure de facturation appropriée dans la commande.
Une réservation correspond à un nombre de minutes bloquées dans l’agenda et la commande peut décider de refléter ce nombre de minutes ou non: on pourrait avoir une réservation d’une journée et une facturation d’une demi-journée seulement par exemple.

Bonne journée

Okay ! donc c’était une confusion de ma part.

Y a-t-il un descriptif de ces principes de fonctionnement quelque part ?
Sinon, puis je avoir un exemple d’appel API de création de commande incluant un UOM ? (ce qui me permettrait de créer des commandes correctement adressées en unité et quantité)