Création de commande avec TVA [API]

Je rencontre un problème pour la création d’une commande avec TVA

Voici les arguments envoyés :

pour Sales Order<pre>Array
(
    [customer] => WEB-m-----@gmail.com
    [items] => Array
        (
            [0] => Array
                (
                    [item_booking] => STO-BOOK-2023-00290
                    [item_code] => LPR
                    [delivery_date] => 2023-10-20
                    [qty] => 1
                    [uom] => Jour
                    [description] => Du 20/10/2023 09:00:00 au 20/10/2023 18:00:00
                    [rate] => 40
                    [base_net_rate] => 33.333333
                    [base_net_amount] => 33.333333
                    [tax_rate] => 20
                    [tax_amount] => 6.67
                    [total_amount] => 40
                )

        )

    [base_total] => 40
    [base_net_total] => 33.333333
    [total_qty] => 1
    [total] => 40
    [net_total] => 33.333333
    [taxes_and_charges] => TVA 20%
    [total_taxes_and_charges] => 6.67
    [base_total_taxes_and_charges] => 6.67
    [total_amount] => 40
    [base_grand_total] => 40
)

La commande est bien enregistrée, mais aucune taxe n’apparait sur la commande
(seulement la mention « TVA 20% » dans le champ « Modèle de taxes et frais de vente »

Manque-t-il un champ spécifique pour correctement enregistrer la TVA (ici 1 article à 33.33 HT = 40 TTC) ?
Faut-il formater le champ ‹ other_charges_calculation › en HTML pour avoir l’affichage du tableau des taxes ?

Merci de votre aide

Réponse de l’ API :

DokosAPIResponse Object
(
    [status_code] => 200
    [success] => 1
    [headers] => Array
        (
        )

    [data] => Array
        (
            [data] => Array
                (
                    [name] => C202300060
                    [owner] => m-----+api@gmail.com
                    [creation] => 2023-07-26 11:51:39.899746
                    [modified] => 2023-07-26 11:51:39.899746
                    [modified_by] => m-----+api@gmail.com
                    [docstatus] => 0
                    [idx] => 0
                    [title] => {customer_name}
                    [naming_series] => C.YYYY.
                    [customer] => WEB-m-----@gmail.com
                    [customer_name] => WEB-m-----@gmail.com
                    [order_type] => Sales
                    [skip_delivery_note] => 1
                    [amended_from] => 
                    [company] => LC
                    [transaction_date] => 2023-07-26
                    [delivery_date] => 2023-10-20
                    [po_no] => 
                    [po_date] => 
                    [tax_id] => 
                    [cost_center] => 
                    [project] => 
                    [customer_address] => 
                    [address_display] => 
                    [contact_person] => 
                    [contact_display] => 
                    [contact_phone] => 
                    [contact_mobile] => 
                    [contact_email] => 
                    [company_address] => 
                    [company_address_display] => 
                    [shipping_address_name] => 
                    [shipping_address] => 
                    [customer_group] => Tarifs tout public
                    [territory] => France
                    [currency] => EUR
                    [conversion_rate] => 1
                    [selling_price_list] => Tarif tout public
                    [price_list_currency] => EUR
                    [plc_conversion_rate] => 1
                    [ignore_pricing_rule] => 0
                    [set_warehouse] => 
                    [scan_barcode] => 
                    [total_qty] => 1
                    [base_total] => 40
                    [base_net_total] => 40
                    [total_net_weight] => 0
                    [total] => 40
                    [net_total] => 40
                    [tax_category] => 
                    [shipping_rule] => 
                    [incoterm] => 
                    [named_place] => 
                    [taxes_and_charges] => TVA 20%
                    [other_charges_calculation] => 
                    [base_total_taxes_and_charges] => 0
                    [total_taxes_and_charges] => 0
                    [loyalty_points] => 0
                    [loyalty_amount] => 0
                    [coupon_code] => 
                    [apply_discount_on] => Grand Total
                    [base_discount_amount] => 0
                    [additional_discount_percentage] => 0
                    [discount_amount] => 0
                    [base_grand_total] => 40
                    [base_rounding_adjustment] => 0
                    [base_rounded_total] => 40
                    [base_in_words] => Quarante Euro
                    [grand_total] => 40
                    [rounding_adjustment] => 0
                    [rounded_total] => 40
                    [in_words] => Quarante Euro
                    [advance_paid] => 0
                    [disable_rounded_total] => 0
                    [payment_terms_template] => 
                    [tc_name] => 
                    [terms] => 
                    [is_internal_customer] => 0
                    [represents_company] => 
                    [inter_company_order_reference] => 
                    [party_account_currency] => 
                    [source] => 
                    [campaign] => 
                    [external_reference] => 
                    [language] => fr
                    [letter_head] => LC
                    [select_print_heading] => 
                    [group_same_items] => 0
                    [status] => Draft
                    [delivery_status] => Not Delivered
                    [per_delivered] => 0
                    [per_billed] => 0
                    [per_picked] => 0
                    [billing_status] => Not Billed
                    [sales_partner] => 
                    [amount_eligible_for_commission] => 0
                    [commission_rate] => 0
                    [total_commission] => 0
                    [from_date] => 
                    [to_date] => 
                    [subscription] => 
                    [auto_repeat] => 
                    [doctype] => Sales Order
                    [sales_team] => Array
                        (
                        )

                    [pricing_rules] => Array
                        (
                        )

                    [items] => Array
                        (
                            [0] => Array
                                (
                                    [name] => d7129e5ac9
                                    [owner] => m-----+api@gmail.com
                                    [creation] => 2023-07-26 11:51:39.899746
                                    [modified] => 2023-07-26 11:51:39.899746
                                    [modified_by] => m-----+api@gmail.com
                                    [docstatus] => 0
                                    [idx] => 1
                                    [item_code] => LPR
                                    [customer_item_code] => 
                                    [ensure_delivery_based_on_produced_serial_no] => 0
                                    [delivery_date] => 2023-10-20
                                    [item_name] => LPR
                                    [description] => Du 20/10/2023 09:00:00 au 20/10/2023 18:00:00
                                    [item_group] => Salles de réunion
                                    [brand] => 
                                    [image] => /files/IMG_8034.jpeg
                                    [qty] => 1
                                    [stock_uom] => 1/2 journée
                                    [uom] => Jour
                                    [conversion_factor] => 1
                                    [stock_qty] => 1
                                    [price_list_rate] => 40
                                    [base_price_list_rate] => 40
                                    [margin_type] => 
                                    [margin_rate_or_amount] => 0
                                    [rate_with_margin] => 0
                                    [discount_percentage] => 0
                                    [discount_amount] => 0
                                    [base_rate_with_margin] => 0
                                    [rate] => 40
                                    [amount] => 40
                                    [item_tax_template] => 
                                    [base_rate] => 40
                                    [base_amount] => 40
                                    [pricing_rules] => 
                                    [stock_uom_rate] => 40
                                    [is_free_item] => 0
                                    [grant_commission] => 0
                                    [net_rate] => 40
                                    [net_amount] => 40
                                    [base_net_rate] => 40
                                    [base_net_amount] => 40
                                    [billed_amt] => 0
                                    [valuation_rate] => 0
                                    [gross_profit] => 40
                                    [delivered_by_supplier] => 0
                                    [supplier] => 
                                    [weight_per_unit] => 0
                                    [total_weight] => 0
                                    [weight_uom] => 
                                    [warehouse] => Magasins - LC
                                    [target_warehouse] => 
                                    [quotation_item] => 
                                    [prevdoc_docname] => 
                                    [against_blanket_order] => 0
                                    [blanket_order] => 
                                    [blanket_order_rate] => 0
                                    [bom_no] => 
                                    [projected_qty] => 0
                                    [actual_qty] => 0
                                    [ordered_qty] => 0
                                    [planned_qty] => 0
                                    [work_order_qty] => 0
                                    [delivered_qty] => 0
                                    [produced_qty] => 0
                                    [returned_qty] => 0
                                    [picked_qty] => 0
                                    [additional_notes] => 
                                    [item_booking] => STO-BOOK-2023-00290
                                    [item_booking_start] => 2023-10-20 09:00:00
                                    [item_booking_end] => 2023-10-20 18:00:00
                                    [page_break] => 0
                                    [item_tax_rate] => []
                                    [transaction_date] => 2023-07-26
                                    [material_request] => 
                                    [purchase_order] => 
                                    [material_request_item] => 
                                    [purchase_order_item] => 
                                    [tax_rate] => 20
                                    [tax_amount] => 6.67
                                    [total_amount] => 40
                                    [parent] => C202300060
                                    [parentfield] => items
                                    [parenttype] => Sales Order
                                    [doctype] => Sales Order Item
                                    [__unsaved] => 1
                                )

                        )

                    [payment_schedule] => Array
                        (
                            [0] => Array
                                (
                                    [name] => efdbc5292e
                                    [owner] => 
                                    [creation] => 2023-07-26 11:51:39.955054
                                    [modified] => 2023-07-26 11:51:39.955054
                                    [modified_by] => m-----+api@gmail.com
                                    [docstatus] => 0
                                    [idx] => 1
                                    [payment_term] => 
                                    [description] => 
                                    [due_date] => 2023-07-26
                                    [mode_of_payment] => 
                                    [invoice_portion] => 100
                                    [discount_type] => 
                                    [discount_date] => 
                                    [discount] => 0
                                    [payment_amount] => 40
                                    [outstanding] => 40
                                    [paid_amount] => 0
                                    [discounted_amount] => 0
                                    [base_payment_amount] => 40
                                    [parent] => C202300060
                                    [parentfield] => payment_schedule
                                    [parenttype] => Sales Order
                                    [doctype] => Payment Schedule
                                )

                        )

                    [packed_items] => Array
                        (
                        )

                    [taxes] => Array
                        (
                        )

                )

        )

    [errors] => Array
        (
        )

    [content_type:protected] => application/json

Bonjour,

Les taxes sont calculées en fonction des lignes de la table taxes uniquement, le champ tax_rate d’une ligne d’article est uniquement indicative je crois bien.

Cette ligne de taxe issue du modèle de taxe est ajoutée par l’interface graphique, mais pas par le contrôleur Python (c’est un bug effectivement).

Je sais qu’il y a une méthode set_taxes() qui s’occupe de ça, et qui n’est pas appelée par défaut. Elle ajoute les lignes issues du modèle de taxe, uniquement pour les nouveaux documents (doc.is_new()) qui n’ont pas de lignes de taxe (len(doc.taxes) == 0), deux conditions réunies ici.

Ensuite, la table HTML des taxes est calculée automatiquement, de même que la plupart des valeurs de la commande (total, etc.)


Solution

Je vois une option simple pour contourner le bug : créer un Script Serveur dans Dokos qui va s’occuper d’appeler doc.set_taxes() à la création d’une commande.

Corentin

Je sais qu’en Python le code minimal pour créer une commande est le suivant, pas besoin d’indiquer les prix s’ils sont dans Dokos :

Code Python
so = frappe.new_doc("Sales Order")
so.update({
  "customer": "NOM DU CLIENT",
  "items": [{ "item_code": "CODE ARTICLE", "qty": 1  }],
  "taxes_and_charges": "TVA 20% Collectée - ABC"
})
so.set_taxes()  # <--- ligne importante
so.save()

Pour l’instant, set_taxes n’est pas appelable depuis l’API, et n’est pas appelée automatiquement à la sauvegarde (c’est un bug). Donc la solution du script serveur me semble la plus simple.

Donc avec l’API REST, la payload JSON minimale pour créer une commande est donc :

{
  "customer": "NOM DU CLIENT",
  "items": [ { "item_code": "NOM DE L'ARTICLE", "qty": 1 } ],
  "taxes_and_charges": "TVA 20% Collectée - ABC",
  "order_type": "Shopping Cart",
}

Mais il faut ajouter le script serveur suivant (tu peux copier-coller ce code dans la GUI Dokos pour le créer rapidement) :

{
  "name": "DĂ©finir taxes sur commandes API",
  "reference_doctype": "Sales Order",
  "doctype_event": "Before Insert",
  "script": "doc.set_taxes()",
  "script_type": "DocType Event",
  "doctype": "Server Script"
}

J’ai testé ça et ça fonctionne bien.

Corentin

Bonjour,

Pour compléter la réponse de Corentin, je pense que la meilleure manière d’indiquer la TVA est d’ajouter des lignes de taxes associées à la clé taxes.

Personnellement je ne suis pas forcément favorable au fait que la TVA soit calculée côté Dokos, car ça implique que la configuration soit parfaitement identique entre les deux systèmes pour que la facture générée par Dokos corresponde à la commande.
A mon avis, la TVA doit être gérée par le logiciel générant la commande (WooCommerce par exemple) et passée telle quelle à Dokos. C’est en tout comme ça que fonctionnent les intégrations existantes.

Ça évite aussi d’avoir ajouter un script serveur dans Dokos (ce qui n’est pas une solution acceptable lorsqu’on veut utiliser l’API).

Bonne journée

Je suis d’accord avec cette solution.
Quelle serait la bonne syntaxe de la clef ‹ taxes › ?

Voici le modèle de document sous-jacent (Sales Taxes and Charges):
https://demo.dokos.cloud/app/doctype/Sales%20Taxes%20and%20Charges

Un exemple basique de syntaxe serait:

[
  {
    "charge_type": "On Net Total",
    "account_head": "445710 - TVA 20% - DKY",
    "description": "TVA 20%",
    "rate": 20
  }
]

Il est possible de passer directement le montant de TVA en utilisant le type de calcul (champ charge_type) « Actual »

Merci pour l’info, je vais formater ca et voir le résultat !