Esta no es la respuesta completa, pero está cerca. Sin embargo, no importa cómo trabaje con los datos, no puedo entender cómo se te ocurre cash_has
. También lo mantengo en SQL sin procesar porque creo que sería más útil y no debería ser difícil volver a convertirlo en un generador de consultas. Tampoco conozco los nombres exactos de las columnas, por lo que es posible que deba corregir algunos de ellos.
SELECT
COALESCE(outlets_admin.name, outlets.name) AS outlet,
COALESCE(boys_admin.name, boys.name) AS delivery_boy,
SUM(IF(cm.source_type = 'admin', amount, 0)) AS cash_taken,
SUM(IF(cm.source_type = 'deliveryBoy', amount, 0)) AS cash_returned,
SUM(IF(cm.source_type = 'admin', amount, 0)) - SUM(IF(cm.source_type = 'deliveryBoy', amount, 0)) AS cash_has
FROM delivery_cash_manages cm
LEFT JOIN outlets ON outlets.id = cm.destination_id AND cm.source_type = 'deliveryBoy'
LEFT JOIN delivery_boys boys ON boys.id = cm.source_id AND cm.source_type = 'deliveryBoy'
LEFT JOIN outlets outlets_admin ON outlets_admin.id = cm.source_id AND cm.source_type = 'admin'
LEFT JOIN delivery_boys boys_admin ON boys_admin.id = cm.destination_id AND cm.source_type = 'admin'
WHERE COALESCE(outlets.id, outlets_admin.id) = '2' # This is where you plug in your $outlet_id
GROUP BY outlet, delivery_boy
Sin embargo, la razón por la que recibe un error con su consulta es que si agrupa por cualquier cosa, debe agrupar por todo lo que seleccione que no sean columnas agregadas (funciones como suma, máx., promedio).