Ordertotalen (WooCommerce)

Uit De Vliegende Brigade
Naar navigatie springen Naar zoeken springen

Wat betekenen precies de getallen onder wp-admin » WooCommerce » Reports? En kan ik dat automatiseren?

WooCommerce Order Report

In eerste aanleg is het allemaal best eenvoudig:

WooCommerce order report
Dezelfde gegevens - Via SQL
Onderdeel Opmerkingen
Order-datum Datum waarop de order is aangemaakt - Veld wp_posts.post_date. Het is dus niet de datum waarop de order status Completed heeft gekregen
Gross sales in this period Verkoopbedrag
Net sales in this period Omzet, vermoedelijk ex. bezorging (maar dat kan ik hier niet zien)

WooCommerce Order Report - Refund

Nu wordt het ingewikkelder:

  • Op 8 april is er een order geplaatst met verkoopbedrag van € 9,95
  • Op 16 mei is deze order geannuleerd en het bedrag terugbetaald.
WP Reports: Deze order is opgenomen in het overzicht over 8 april, alsof deze niet is geannuleerd
Getallen over 8 april: Zij-aan-zij SQL & WP Reporting (=order-overzicht in WooCommerce):
  • In SQL (eigen code) had ik er voor gekozen om te filteren op order-status completed. Orders met status refunded worden dus niet meegenomen
  • WP Reporting: De order is wél meegenomen, want er wordt gefilterd op beide statussen
Deze geannuleerde order kan ook via SQL gemakkelijk boven water getoverd worden, door post_status wc-refunded mee te nemen. Maar waarom zou je?
Getallen over mei (de maand waarin de order geannuleerd werd): Zij-aan-zij SQL & WP Reporting: Deze laatste reporteert een omzet die € 40,80 lager is dan wat ik via SQL krijg, terwijl het aantal orders gelijk is ⇒ De omzet van de geannulleerde order is in mindering gebracht op de omzet, maar het aantal orders is ongewijzigd en het is niet te traceren waar dat bedrag van € 40,80 vandaan komt, tenzij je dat vantevoren al weet, zoals in dit geval - En dat is een probleem

Het probleem met WooCommerce Order Report

WooCommerce Order Reports gaat om met refunds op een manier waarvan ik denk dat het problematisch is:

  • Als een order (die later wordt geannuleerd) wordt geplaatst, wordt de bijbehorende omzet geïncorporeerd in de omzet van de betreffende maand - so far, so good
  • Op het moment dat die order geannulleerd wordt, wordt de omzet in de maand waarin de order is geannulleerd, navenant verlaagd - Ook niet zo gek
  • Het aantal orders verandert echter niet, en je kunt in de omzetcijfers over de maand waarin een order is geannuleerd, niet traceren waarom het orderbedrag lager is dan verwacht - En dat is een probleem.

Welliswaar vermeldt WP Reporting dat er een bedrag aan refunds is, maar je kunt niet gemakkelijk traceren welke annulering welke omzet heeft geaffecteerd. Het feit dat het aantal orders niet verandert in een maand waarin een annulering plaatsvindt, zorgt dat de totaalbedragen niet kloppen.

Oplossingen

Oplossing (1): Twee keer incorporeren

Neem de oorspronkelijke order op in de administratie + een credit-order op het moment dat deze geannuleerd wordt. Da's hoe het in boekhoudingen meestal gaat.

  • Voordeel: Helemaal duidelijk wat er gebeurd
  • Nadeel: Beetje omslachtig, want twee mutaties - Net als in een boekhouding.

Oplossing (2): Helemaal niet incorporeren

De andere aanpak: De betreffende order helemaal niet incorporeren. Dit is was ik in SQL doe.

  • Voordeel: Gemakkelijk
  • Nadeel: Als annulatie flink later plaatsvindt dan de oorspronkelijke order (zoals in de casus hierboven), dan klopt de administratie een tijdje niet.

Conclusie: Gebruik Order Reports niet

  • Gewoon niet gebruiken, want je kunt refund-gerelateerde mutaties niet traceren en totaalbedragen kloppen niet meer
  • Waarschijnlijk kloppen de getallen over de lange termijn wel, maar het feit dat deze niet te traceren zijn en getallen gewoon niet kloppene, vind ik onaanvaardbaar.

Eigen oplossing

Een pure SQL-oplossing:

#
# Read-out monthly revenue figures webshops server dvb12
################################################################################
#
#
# Output
########################################
#
# * First figure: "Sales" - "Verkoopbedrag"
# * Second figure: "Revenue" - "Omzet"
#
#
# Recommendations
########################################
#
# * Develop similar script for sites on server "dvb13"
# * Use the same associate array loop as now used for site maintenance 
#   + use WP-CLI as SQL-wrapper
#
#
################################################################################
# Exchange rates
################################################################################
#
# * Value of 1 unit expressed in euros
# * Try to get at least 3 significant numbers. This will often also be the
#   maximum relevant number, because of fluctuations
#
set @aud=0.66715944;	# https://www.xe.com/currencyconverter/convert/?Amount=1&From=AUD&To=EUR
set @cad=0.74248581;	# https://www.google.com/search?q=1%20cad%20to%20eur
set @chf=0.96594098;	# https://www.xe.com/currencyconverter/convert/?Amount=1&From=CHF&To=EUR
set @cny=0.14113558;	# https://www.xe.com/currencyconverter/convert/?Amount=1&From=CNY&To=EUR
set @gbp=1.1808518;		# https://www.xe.com/currencyconverter/convert/?Amount=1&From=GBP&To=EUR
set @czk=0.040544174;	# https://www.xe.com/currencyconverter/convert/?Amount=1&From=CZK&To=EUR
set @dkk=0.13438589;	# https://www.xe.com/currencyconverter/convert/?Amount=1&From=DKK&To=EUR
set @inr=0.012267764;	# https://www.xe.com/currencyconverter/convert/?Amount=1&From=INR&To=EUR
set @jpy=0.0074278196;	# https://www.xe.com/currencyconverter/convert/?Amount=1&From=JPY&To=EUR
set @ngn=0.002295;		# https://www.xe.com/currencyconverter/convert/?Amount=1&From=NGN&To=EUR
set @nzd=0.603;			# https://www.xe.com/currencyconverter/convert/?Amount=1&From=NZD&To=EUR
set @pln=0.215;			# https://www.xe.com/currencyconverter/convert/?Amount=1&From=PLN&To=EUR
set @sek=0.09518;		# https://www.xe.com/currencyconverter/convert/?Amount=1&From=SEK&To=EUR
set @try=0.0596;		# https://www.xe.com/currencyconverter/convert/?Amount=1&From=TRY&To=EUR
set @uah=0.0324;		# https://www.xe.com/currencyconverter/convert/?Amount=1&From=UAH&To=EUR
set @usd=0.95277;		# https://www.xe.com/currencyconverter/convert/?Amount=1&From=USD&To=EUR


################################################################################
# Set variable for month & year
################################################################################
#
# Set to last month
########################################
#
# set @month=date_format(now(),"%m")-1;
# set @month=if(@month=0,12,@month);
# set @year=date_format(now(),"%Y");
# set @year=if(@month=12,@year-1,@year);


# Set manually
########################################
#
set @month=5;
set @year=2022;


################################################################################
# 4 - example_ch
################################################################################
#
select
    "example_ch" as webshop,
    round(@chf*sum(wp_postmeta_order_total.meta_value),2) as sales,
    round(@chf*sum(round(wp_postmeta_order_total.meta_value - wp_postmeta_order_shipping.meta_value - 
     wp_postmeta_order_shipping_vat.meta_value - wp_postmeta_vat.meta_value, 2)),2) as subtotal
from
    example_ch.wp_posts
join
    example_ch.wp_postmeta as wp_postmeta_order_shipping on wp_posts.ID = wp_postmeta_order_shipping.post_id
join
    example_ch.wp_postmeta as wp_postmeta_order_shipping_vat on wp_posts.ID = wp_postmeta_order_shipping_vat.post_id
join
    example_ch.wp_postmeta as wp_postmeta_order_total on wp_posts.ID = wp_postmeta_order_total.post_id
join
    example_ch.wp_postmeta as wp_postmeta_vat on wp_posts.ID = wp_postmeta_vat.post_id    
where
    post_type = "shop_order" and post_status = "wc-completed" and wp_postmeta_order_total.meta_key="_order_total" and wp_postmeta_vat.meta_key="_order_tax"
    and wp_postmeta_order_shipping.meta_key="_order_shipping" and wp_postmeta_order_shipping_vat.meta_key="_order_shipping_tax" and
    date_format(post_date, "%Y")=@year and date_format(post_date, "%m")=@month


################################################################################
# 5 - example_uk
################################################################################
#
union select
    "example_uk" as webshop,
    round(@gbp*sum(wp_postmeta_order_total.meta_value),2) as sales,
    round(@gbp*sum(round(wp_postmeta_order_total.meta_value - wp_postmeta_order_shipping.meta_value - 
     wp_postmeta_order_shipping_vat.meta_value - wp_postmeta_vat.meta_value, 2)),2) as subtotal
from
    example_uk.wp_posts
join
    example_uk.wp_postmeta as wp_postmeta_order_shipping  # for "subtotal"
    on
    wp_posts.ID = wp_postmeta_order_shipping.post_id
join
    example_uk.wp_postmeta as wp_postmeta_order_shipping_vat  # for "subtotal"
    on
    wp_posts.ID = wp_postmeta_order_shipping_vat.post_id
join
    example_uk.wp_postmeta as wp_postmeta_order_total # For "sales" & "subtotal"
    on
    wp_posts.ID = wp_postmeta_order_total.post_id
join
    example_uk.wp_postmeta as wp_postmeta_vat     # For "subtotal"
    on
    wp_posts.ID = wp_postmeta_vat.post_id    
where
    post_type = "shop_order"
    and
    post_status = "wc-completed"
    and
    wp_postmeta_order_total.meta_key="_order_total"
    and
    wp_postmeta_vat.meta_key="_order_tax"
    and
    wp_postmeta_order_shipping.meta_key="_order_shipping"
    and
    wp_postmeta_order_shipping_vat.meta_key="_order_shipping_tax"
    and
    date_format(post_date, "%Y")=@year
    and
    date_format(post_date, "%m")=@month

# Etc.

Bronnen