At DrupalCamp Cologne there was a suggestion on adding an hook_product() that lets us edit a product on product load. So we could solve the VAT/GST calculation on product load.
On a TrainSession back from Cologne to Hannover SteffenR and me worked out some concept. I hope this can help to create a clear structure for future releases.
Some central problems of current ubercart seems to be,
* No flexible prize adjust
* no itemization of prize adjusts
* no logging of current currency, taxes, ... in order ?
* no arranging of different prize adjust possible (e.g. to do tax before discount or discount before tax)
Therefore I think we need to itemize the prizes (sell prize, costs, list prize), e.g. as objects, with one property that collects the adjustments.
(object) $prize
-> (str) currency //current sitewide currency?? (for logging)
-> (array) adjustments //list of nested arrays
[0] => (array)adjustment 1
[1] => (array)adjustment 2
[2] => (array)adjustment 3
...
-> (obj) sell_prize
-> sell_prize
... possible additional values provides by modules ...
-> with_taxes
-> without_taxes
-> without_discount
...
-> (obj) list_prize
... like sell prize ...
-> (obj) costs
... like sell prize ...$prize->sell prize->sell_prize would be the prize customer has to pay. The other components could be used to show adjustments, e.g. on invoice or for further calculation or statistics (shipping costs)
The adjustments and additional components could be processed after calling hook_product to ensure propper logging of information and providing a integrated method for applying changes to prizes.
The adjustments would be applied on sell_prize, costs, list_prize.
Each adjustment could be described by:
[type] =>
* label // translatable name of adjustment
* option // option as selector for adjustment types: e.g. tax rate
* value // value that indicates an adjustment on the current prize valueIn an hook_product_adjust_info() this adjustment types could be declared with arrays
*type //e.g. tax, fee, shipping_per_product, discount
*title //human readable, translatable label
*adjust callback //a callback function that acts on the current productAdjustment could act depending on product costs or list prizes.
E.g. apply sell_prize to be 120% of costs, or to be 90% of list prize for automated prize regulation.
<?php
/**
* @param $product
* the product object retrieved from hook_product
* @param $type
* type of adjustment
* @param $option
* attribute for callback
* @param $value
* value that indicates adjustment
* @param $back
* perator for calculationg backwards, if set to true
* @return (array)
*/
function prizesminus1_adjust_callback($product,$type,$option,$value,$back=FALSE){
...
return array(
'sell_prize'=>array('sell_prize'=>-1,'without_taxes'=>-1,'with_taxes'=>-1.17),
'costs'=>array('costs'=>-1),
);
}
?>These adjustment values on the current prize and additional components will be applied after each other, so there will be allways the actual $product with all applied adjustments listed.
The new product_load could look like this:
<?php
function uc_product_load(&$node) {
$product = db_fetch_object(db_query('SELECT model, list_price, cost, sell_price, weight, weight_units, length, width, height, length_units, pkg_qty, default_qty, unique_hash, ordering, shippable FROM {uc_products} WHERE vid = %d', $node->vid));
module_invoke_all("product",$product);//product by Ref
$adjustment_infos = module_invoke_all("prize_adjustment_info");
foreach ($product->adjustments as $adjustment){
$info = $adjustment_infos[$adjustment['type']];
$product4val = $product;//ensures product by value
$return = call_user_func($info['adjust callback'],$product4val,$adjustment['type'],$adjustment['option'],$adjustment['value']);
foreach($return as $pkey=>$obj){
foreach ($obj as $ckey=>$component){
$product->$pkey[$ckey] += $component;
}
}
}
return $product;
}
?>By implementing such hook, modules like uc_attribute, uc_fee, uc_discount could easily use this hook to apply prize adjustments per product(!).

)

