Commit 125a82ce authored by Malcolm Blaney's avatar Malcolm Blaney

Added "purchase-pre-order" substitution so that copying orders for

next week is not tied to time invoices are sent out (though this
can still happen too). Fixed some stock tracking bugs when adding
purchases, also wasn't checking the quantity of composite items
being added to purchases. Removing purchases can now be configured
to only remove purchases where quota hasn't been met. Stock
adjustments are now stored as the delta rather than the new total
so that reconcilliation can be done more easily.
parent 37d91521
...@@ -290,14 +290,22 @@ class Banking extends Base { ...@@ -290,14 +290,22 @@ class Banking extends Base {
return array($user_list, $buyer_groups); return array($user_list, $buyer_groups);
} }
public function AllSettings() { public function AllSettings($organisation = true) {
$settings = array(); $settings = array();
$organiser = new Organiser($this->user, $this->owner); $query = "";
if ($organisation) {
$organiser = new Organiser($this->user, $this->owner);
$query = 'SELECT banking.user, reference, name, number, bsb, credit, '.
'surcharge, next_week, buyer_group FROM banking LEFT JOIN users ON '.
'banking.user = users.user WHERE '.$organiser->GroupQuery();
}
else {
$query = 'SELECT banking.user, reference, name, number, bsb, credit, '.
'surcharge, next_week, buyer_group FROM banking LEFT JOIN users ON '.
'banking.user = users.user WHERE '.
'users.system_group = "'.$this->user->group.'"';
}
$mysqli = connect_db(); $mysqli = connect_db();
$query = 'SELECT banking.user, reference, name, number, bsb, credit, '.
'surcharge, buyer_group FROM banking LEFT JOIN users ON '.
'banking.user = users.user WHERE '.$organiser->GroupQuery();
if ($result = $mysqli->query($query)) { if ($result = $mysqli->query($query)) {
while ($banking = $result->fetch_assoc()) { while ($banking = $result->fetch_assoc()) {
$settings[$banking["user"]] = $settings[$banking["user"]] =
...@@ -307,6 +315,7 @@ class Banking extends Base { ...@@ -307,6 +315,7 @@ class Banking extends Base {
"bsb" => $banking["bsb"], "bsb" => $banking["bsb"],
"credit" => (int)$banking["credit"], "credit" => (int)$banking["credit"],
"surcharge" => (int)$banking["surcharge"], "surcharge" => (int)$banking["surcharge"],
"nextWeek" => $banking["next_week"],
"buyerGroup" => $banking["buyer_group"]); "buyerGroup" => $banking["buyer_group"]);
} }
$result->close(); $result->close();
......
...@@ -98,9 +98,18 @@ class Contact extends Base { ...@@ -98,9 +98,18 @@ class Contact extends Base {
else { else {
$sender_name .= " <".$sender.">"; $sender_name .= " <".$sender.">";
} }
$cc = $this->Substitute("system-sender-cc");
$bcc = $this->Substitute("system-sender-bcc");
$headers = "MIME-Version: 1.0\r\n". $headers = "MIME-Version: 1.0\r\n".
"Content-type: text/html; charset=iso-8859-1\r\n". "Content-type: text/html; charset=iso-8859-1\r\n".
"From: ".$sender_name."\r\n"; "From: ".$sender_name."\r\n";
if ($cc != "") {
$headers .= "Cc: ".$cc."\r\n";
}
if ($bcc != "") {
$headers .= "Bcc: ".$bcc."\r\n";
}
if ($reply_to != "") { if ($reply_to != "") {
$headers .= "Reply-To: ".$reply_to."\r\n"; $headers .= "Reply-To: ".$reply_to."\r\n";
} }
......
...@@ -409,92 +409,6 @@ class Invoice extends Base { ...@@ -409,92 +409,6 @@ class Invoice extends Base {
public function Update() { public function Update() {
// This is called when the version of the module is updated, // This is called when the version of the module is updated,
// to provide a way to update or modify tables etc.. // to provide a way to update or modify tables etc..
$mysqli = connect_db();
$query = 'ALTER TABLE invoice DROP invoice_text';
if (!$mysqli->query($query)) {
$this->Log("Invoice->Update 1: ".$mysqli->error);
}
$query = 'UPDATE template SET label = "invoice-group-cc" WHERE '.
'label = "invoice-stock-cc"';
if (!$mysqli->query($query)) {
$this->Log("Invoice->Update 2: ".$mysqli->error);
}
$query = 'UPDATE template SET label = "invoice-group-bcc" WHERE '.
'label = "invoice-stock-bcc"';
if (!$mysqli->query($query)) {
$this->Log("Invoice->Update 3: ".$mysqli->error);
}
$query = 'UPDATE template SET label = "invoice-group-email" WHERE '.
'label = "invoice-stock-email"';
if (!$mysqli->query($query)) {
$this->Log("Invoice->Update 4: ".$mysqli->error);
}
$query = 'UPDATE template SET label = "invoice-group-subject" WHERE '.
'label = "invoice-stock-subject"';
if (!$mysqli->query($query)) {
$this->Log("Invoice->Update 5: ".$mysqli->error);
}
$query = 'UPDATE template SET label = "invoice-intro-no-orders" WHERE '.
'label = "invoice-stock-no-orders"';
if (!$mysqli->query($query)) {
$this->Log("Invoice->Update 6: ".$mysqli->error);
}
$query = 'UPDATE template SET label = "invoice-intro-orders" WHERE '.
'label = "invoice-stock-orders"';
if (!$mysqli->query($query)) {
$this->Log("Invoice->Update 7: ".$mysqli->error);
}
$query = 'UPDATE template SET label = "invoice-group-format" WHERE '.
'label = "invoice-group-stock-format"';
if (!$mysqli->query($query)) {
$this->Log("Invoice->Update 8: ".$mysqli->error);
}
$query = 'UPDATE template SET label = "invoice-organisation-sender" '.
'WHERE label = "organisation-sender"';
if (!$mysqli->query($query)) {
$this->Log("Invoice->Update 9: ".$mysqli->error);
}
$query = 'UPDATE template SET label = "invoice-organisation-sender-name" '.
'WHERE label = "organisation-sender-name"';
if (!$mysqli->query($query)) {
$this->Log("Invoice->Update 10: ".$mysqli->error);
}
$query = 'UPDATE template SET label = "invoice-organisation-email" WHERE '.
'label = "organisation-stock-email"';
if (!$mysqli->query($query)) {
$this->Log("Invoice->Update 11: ".$mysqli->error);
}
$query = 'UPDATE template SET label = "invoice-organisation-subject" '.
'WHERE label = "organisation-stock-subject"';
if (!$mysqli->query($query)) {
$this->Log("Invoice->Update 12: ".$mysqli->error);
}
$query = 'UPDATE template SET label = "invoice-organisation-cc" '.
'WHERE label = "organisation-stock-cc"';
if (!$mysqli->query($query)) {
$this->Log("Invoice->Update 13: ".$mysqli->error);
}
$query = 'UPDATE template SET label = "invoice-organisation-bcc" '.
'WHERE label = "organisation-stock-bcc"';
if (!$mysqli->query($query)) {
$this->Log("Invoice->Update 14: ".$mysqli->error);
}
$query = 'UPDATE template SET label = "invoice-organisation-format" '.
'WHERE label = "organisation-stock-format"';
if (!$mysqli->query($query)) {
$this->Log("Invoice->Update 15: ".$mysqli->error);
}
$query = 'UPDATE template SET label = "invoice-extra-column" WHERE '.
'label = "organisation-stock-extra-column"';
if (!$mysqli->query($query)) {
$this->Log("Invoice->Update 16: ".$mysqli->error);
}
$mysqli->close();
// Besides all the name changes above there's also a new template for
// individual order subject lines.
$template = array('"invoice-order-subject","","Order for next week"');
$this->AddTemplate($template);
} }
public function UpdateScript($path) { public function UpdateScript($path) {
......
...@@ -166,7 +166,7 @@ class Organiser extends Base { ...@@ -166,7 +166,7 @@ class Organiser extends Base {
$us_message)); $us_message));
$sender = $this->Substitute("organiser-sender", "/!host/", $sender = $this->Substitute("organiser-sender", "/!host/",
$this->user->config->ServerName()); $this->user->config->ServerName());
$sender_name = $this->Substitute("system-sender-name"); $sender_name = $this->Substitute("organiser-sender-name");
if ($sender_name == "") { if ($sender_name == "") {
$sender_name = $sender; $sender_name = $sender;
} }
......
This diff is collapsed.
...@@ -182,6 +182,7 @@ class Reader extends Base { ...@@ -182,6 +182,7 @@ class Reader extends Base {
'"",".reader-group","background-color","#eeeeee"', '"",".reader-group","background-color","#eeeeee"',
'"",".reader-group","border","1px solid #aaaaaa"', '"",".reader-group","border","1px solid #aaaaaa"',
'"",".reader-group","border-radius","2px"', '"",".reader-group","border-radius","2px"',
'"",".reader-item .description","overflow","auto"',
'"",".reader a","color","#666666"', '"",".reader a","color","#666666"',
'"",".reader a:hover","color","#999999"', '"",".reader a:hover","color","#999999"',
'"",".reader","font-family","Verdana,Arial"'); '"",".reader","font-family","Verdana,Arial"');
......
...@@ -254,16 +254,14 @@ class Stock extends Base { ...@@ -254,16 +254,14 @@ class Stock extends Base {
$time = "11pm"; $time = "11pm";
if (!$this->Run($time)) return; if (!$this->Run($time)) return;
$organiser = new Organiser($this->user, $this->owner); // Order availability is imported by the user and then used here to
// order availability is imported, and then used to overwrite purchase // overwrite purchase availabilty.
// availabilty on the day specified by "stock-order-update".
$run_groups = $this->RunGroups("stock-order-update", $time); $run_groups = $this->RunGroups("stock-order-update", $time);
$mysqli = connect_db(); $mysqli = connect_db();
for ($i = 0; $i < count($run_groups); $i++) { for ($i = 0; $i < count($run_groups); $i++) {
$group = $run_groups[$i];
$this->user = new User($this->owner, $group);
$query = 'UPDATE stock LEFT JOIN users ON stock.user = users.user SET '. $query = 'UPDATE stock LEFT JOIN users ON stock.user = users.user SET '.
'purchase_available = order_available WHERE '.$organiser->GroupQuery(); 'purchase_available = order_available WHERE '.
'users.system_group = "'.$run_groups[$i].'"';
if (!$mysqli->query($query)) { if (!$mysqli->query($query)) {
$this->Log("Stock->Cron: ".$mysqli->error); $this->Log("Stock->Cron: ".$mysqli->error);
} }
...@@ -427,13 +425,6 @@ class Stock extends Base { ...@@ -427,13 +425,6 @@ class Stock extends Base {
public function Update() { public function Update() {
// This is called when the version of the module is updated, // This is called when the version of the module is updated,
// to provide a way to update or modify tables etc.. // to provide a way to update or modify tables etc..
$mysqli = connect_db();
$query = 'ALTER TABLE stock MODIFY unit '.
'ENUM("each","kg","L","variable", "g") NOT NULL';
if (!$mysqli->query($query)) {
$this->Log('Stock->Update: '.$mysqli->error);
}
$mysqli->close();
} }
public function UpdateScript($path) { public function UpdateScript($path) {
...@@ -516,7 +507,7 @@ class Stock extends Base { ...@@ -516,7 +507,7 @@ class Stock extends Base {
$query = 'SELECT name, stock.user, unit, pack_size, base_price, '. $query = 'SELECT name, stock.user, unit, pack_size, base_price, '.
'wholesale_price, retail_price, category, grower FROM stock LEFT JOIN '. 'wholesale_price, retail_price, category, grower FROM stock LEFT JOIN '.
'users ON stock.user = users.user LEFT JOIN stock_supply_group ON '. 'users ON stock.user = users.user LEFT JOIN stock_supply_group ON '.
'stock_supply_group.user = stock.user WHERE '. 'stock_supply_group.user = stock.user WHERE composite = 0 AND '.
'('.$organiser->GroupQuery().') AND '. '('.$organiser->GroupQuery().') AND '.
'(stock_supply_group.system_group = "'.$this->user->group.'" OR '. '(stock_supply_group.system_group = "'.$this->user->group.'" OR '.
'stock_supply_group.system_group = "") '.$available_query. 'stock_supply_group.system_group = "") '.$available_query.
...@@ -701,6 +692,24 @@ class Stock extends Base { ...@@ -701,6 +692,24 @@ class Stock extends Base {
return $supplier; return $supplier;
} }
public function Quota($name, $user, $quantity) {
$quota = false;
$mysqli = connect_db();
$query = 'SELECT pack_size FROM stock WHERE name = "'.$name.'" AND '.
'user = "'.$user.'"';
if ($result = $mysqli->query($query)) {
if ($stock = $result->fetch_assoc()) {
$quota = $quantity >= (float)$stock["pack_size"];
}
$result->close();
}
else {
$this->Log("Stock->Quota: ".$mysqli->error);
}
$mysqli->close();
return $quota;
}
// Private functions below here //////////////////////////////////////////// // Private functions below here ////////////////////////////////////////////
private function AllData() { private function AllData() {
...@@ -1225,22 +1234,36 @@ class Stock extends Base { ...@@ -1225,22 +1234,36 @@ class Stock extends Base {
$mysqli = connect_db(); $mysqli = connect_db();
$name = $mysqli->escape_string($_POST["name"]); $name = $mysqli->escape_string($_POST["name"]);
$user = $mysqli->escape_string($_POST["supplier"]); $user = $mysqli->escape_string($_POST["supplier"]);
$total = $mysqli->escape_string($_POST["total"]); $total = (float)$mysqli->escape_string($_POST["total"]);
$description = $mysqli->escape_string($_POST["description"]); $description = $mysqli->escape_string($_POST["description"]);
$organiser = new Organiser($this->user, $this->owner); $organiser = new Organiser($this->user, $this->owner);
if (!$organiser->MatchUser($user)) { if (!$organiser->MatchUser($user)) {
$mysqli->close();
return array("error" => "Supplier not found"); return array("error" => "Supplier not found");
} }
$adjustment = 0;
// Look up the original stock quantity to calculate the difference.
$query = 'SELECT quantity FROM stock WHERE name = "'.$name.'" '.
'AND user = "'.$user.'"';
if ($result = $mysqli->query($query)) {
if ($stock = $result->fetch_assoc()) {
$adjustment = $total - (float)$stock["quantity"];
}
$result->close();
}
else {
$this->Log("Stock->SaveAdjustment 1: ".$mysqli->error);
}
$query = 'UPDATE stock SET quantity = '.$total.' WHERE name = "'.$name.'" '. $query = 'UPDATE stock SET quantity = '.$total.' WHERE name = "'.$name.'" '.
'AND user = "'.$user.'"'; 'AND user = "'.$user.'"';
if (!$mysqli->query($query)) { if (!$mysqli->query($query)) {
$this->Log("Stock->SaveAdjustment 1: ".$mysqli->error); $this->Log("Stock->SaveAdjustment 2: ".$mysqli->error);
} }
$query = 'INSERT INTO stock_adjustment VALUES ("'.$name.'", "'.$user.'", '. $query = 'INSERT INTO stock_adjustment VALUES ("'.$name.'", "'.$user.'", '.
$total.', "'.$description.'", "'.$this->user->name.'", '.time().')'; $adjustment.', "'.$description.'", "'.$this->user->name.'", '.time().')';
if (!$mysqli->query($query)) { if (!$mysqli->query($query)) {
$this->Log("Stock->SaveAdjustment 2: ".$mysqli->error); $this->Log("Stock->SaveAdjustment 3: ".$mysqli->error);
} }
$mysqli->close(); $mysqli->close();
return array("done" => true); return array("done" => true);
......
...@@ -118,8 +118,7 @@ class Summary extends Base { ...@@ -118,8 +118,7 @@ class Summary extends Base {
$outstanding_text = 'You are currently in credit by: $'. $outstanding_text = 'You are currently in credit by: $'.
number_format($outstanding*-1, 2, ".", ""); number_format($outstanding*-1, 2, ".", "");
} }
$pre_order_available = $this->Substitute("pre-order") === "true" ? $pre_order_available = $this->Substitute("pre-order") === "true";
true : false;
$pre_order_text = $this->Substitute("summary-pre-order", "/!final/", $pre_order_text = $this->Substitute("summary-pre-order", "/!final/",
$this->Substitute("pre-order-final")); $this->Substitute("pre-order-final"));
$purchase_page = $this->Substitute("purchase-page"); $purchase_page = $this->Substitute("purchase-page");
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
if(!this.dobrado.manager){dobrado.manager={};} if(!this.dobrado.manager){dobrado.manager={};}
(function(){'use strict';var manager=null;var purchase=[];var managerGrid=null;var managerGridId="";var allProductsGrid=null;var allProductsGridId="";var allProductsData=[];var currentProduct=null;var currentDate=null;var oneDay=86400000;var confirmRemoveMultiple=false;var currentRemove=0;var composite=false;$(function(){if($(".manager").length===0){return;} (function(){'use strict';var manager=null;var purchase=[];var managerGrid=null;var managerGridId="";var allProductsGrid=null;var allProductsGridId="";var allProductsData=[];var currentProduct=null;var currentDate=null;var oneDay=86400000;var confirmRemoveMultiple=false;var currentRemove=0;var composite=false;$(function(){if($(".manager").length===0){return;}
$("#manager-details-form").dialog({autoOpen:false,modal:true,position:{my:"top",at:"top+50",of:"body"},title:"Edit User Details",width:400});$("#manager-details-form .submit").button().click(editDetails);$(".manager-view-all-dialog").dialog({autoOpen:false,modal:true,position:{my:"top",at:"top+50",of:"body"},title:"Available Products",width:830,height:520,close:function(){if(allProductsGrid){allProductsGrid.gotoCell(0,0);}}});$(".manager .view-all").click(viewAll);$("#manager-form .edit").button({disabled:true}).click(openDialog);$("#manager-form .submit").button().click(submit);$("#manager-form .search").button().click(search);$("#manager-form .remove").button().click(remove);$("#manager-username-input").val("").change(function(){setTimeout(function(){showUser();},10);});$("#manager-username-input").keypress(checkUsernameEnter);$("#manager-product-input").val("").change(function(){setTimeout(function(){showProductFromMenu();},10);});$("#manager-supplier-input").val("").change(function(){setTimeout(function(){showSupplierFromMenu();},10);});$("#manager-product-input").val("");$("#manager-price-input").val("");$("#manager-date-input").val(dobrado.formatDate()).change(clearSearchDates).datepicker({dateFormat:dobrado.dateFormat});$("#manager-start-date-input").val("").change(clearDate).datepicker({dateFormat:dobrado.dateFormat});$("#manager-end-date-input").val("").change(clearDate).datepicker({dateFormat:dobrado.dateFormat});$("#manager-quantity-input").val("");$("#manager-quantity-input").spinner({min:0,spin:setQuantity,change:setQuantity});$(".manager .toggle-search-options").click(function(){$(".manager .search-options").toggle();});$(".grid").each(function(index){if(index===0){managerGridId="#"+$(this).attr("id");} $("#manager-details-form").dialog({autoOpen:false,modal:true,position:{my:"top",at:"top+50",of:"body"},title:"Edit User Details",width:400});$("#manager-details-form .submit").button().click(editDetails);$(".manager-view-all-dialog").dialog({autoOpen:false,modal:true,position:{my:"top",at:"top+50",of:"body"},title:"Available Products",width:830,height:520,close:function(){if(allProductsGrid){allProductsGrid.gotoCell(0,0);}}});$(".manager .view-all").click(viewAll);$("#manager-form .edit").button({disabled:true}).click(openDialog);$("#manager-form .submit").button().click(submit);$("#manager-form .search").button().click(search);$("#manager-form .remove").button().click(remove);$("#manager-username-input").val("").change(function(){setTimeout(function(){showUser();},10);});$("#manager-username-input").keypress(checkUsernameEnter);$("#manager-product-input").val("").change(function(){setTimeout(function(){showProductFromMenu();},10);});$("#manager-supplier-input").val("").change(function(){setTimeout(function(){showSupplierFromMenu();},10);});$("#manager-product-input").val("");$("#manager-price-input").val("");$("#manager-date-input").val(dobrado.formatDate()).change(clearSearchDates).datepicker({dateFormat:dobrado.dateFormat});$("#manager-start-date-input").val("").change(clearDate).datepicker({dateFormat:dobrado.dateFormat});$("#manager-end-date-input").val("").change(clearDate).datepicker({dateFormat:dobrado.dateFormat});$("#manager-quantity-input").val("");$("#manager-quantity-input").spinner({min:0,spin:setQuantity,change:setQuantity});$(".manager .toggle-search-options").click(function(){clearSearchDates();clearDate();$(".manager .search-options").toggle();});$(".grid").each(function(index){if(index===0){managerGridId="#"+$(this).attr("id");}
if(index===1){allProductsGridId="#"+$(this).attr("id");}});if($(".grid").length!==0){$(".grid").hide();var columns=[{id:"date",name:"Date",field:"date",width:110,sortable:true,formatter:Slick.Formatters.Timestamp},{id:"user",name:"Username",field:"user",width:100,sortable:true},{id:"name",name:"Product",field:"name",width:180,sortable:true},{id:"supplier",name:"Supplier",field:"supplier",width:100,sortable:true},{id:"quantity",name:"Quantity",field:"quantity",width:90,sortable:true},{id:"price",name:"Price",field:"price",width:80,sortable:true,formatter:Slick.Formatters.Dollar},{id:"total",name:"Total",field:"total",width:80,sortable:true,formatter:Slick.Formatters.Dollar}];var options={enableColumnReorder:false,forceFitColumns:true};managerGrid=dobrado.grid.instance(managerGridId,[],columns,options);managerGrid.setSelectionModel(new Slick.RowSelectionModel());managerGrid.onClick.subscribe(function(e,item){showPurchase(item.row);});managerGrid.onSort.subscribe(function(e,args){purchase.sort(function(row1,row2){var field=args.sortCol.field;var sign=args.sortAsc?1:-1;var value1=row1[field];var value2=row2[field];if(field==="quantity"||field==="price"||field==="total"){value1=parseFloat(value1);value2=parseFloat(value2);} if(index===1){allProductsGridId="#"+$(this).attr("id");}});if($(".grid").length!==0){$(".grid").hide();var columns=[{id:"date",name:"Date",field:"date",width:110,sortable:true,formatter:Slick.Formatters.Timestamp},{id:"user",name:"Username",field:"user",width:100,sortable:true},{id:"name",name:"Product",field:"name",width:180,sortable:true},{id:"supplier",name:"Supplier",field:"supplier",width:100,sortable:true},{id:"quantity",name:"Quantity",field:"quantity",width:90,sortable:true},{id:"price",name:"Price",field:"price",width:80,sortable:true,formatter:Slick.Formatters.Dollar},{id:"total",name:"Total",field:"total",width:80,sortable:true,formatter:Slick.Formatters.Dollar}];var options={enableColumnReorder:false,forceFitColumns:true};managerGrid=dobrado.grid.instance(managerGridId,[],columns,options);managerGrid.setSelectionModel(new Slick.RowSelectionModel());managerGrid.onClick.subscribe(function(e,item){showPurchase(item.row);});managerGrid.onSort.subscribe(function(e,args){purchase.sort(function(row1,row2){var field=args.sortCol.field;var sign=args.sortAsc?1:-1;var value1=row1[field];var value2=row2[field];if(field==="quantity"||field==="price"||field==="total"){value1=parseFloat(value1);value2=parseFloat(value2);}
if(value1===value2){return 0;} if(value1===value2){return 0;}
if(value1>value2){return sign;} if(value1>value2){return sign;}
...@@ -130,8 +130,10 @@ if(!composite&&user===""){alert("Please enter a username.");return;} ...@@ -130,8 +130,10 @@ if(!composite&&user===""){alert("Please enter a username.");return;}
var priceLevel="price";if(user!==""){priceLevel=manager.buyerGroup[user];if(!priceLevel){priceLevel="retail";}} var priceLevel="price";if(user!==""){priceLevel=manager.buyerGroup[user];if(!priceLevel){priceLevel="retail";}}
var timestamp=Date.now();var date=$("#manager-date-input").datepicker("getDate");if(date){timestamp=parseInt($.datepicker.formatDate("@",date),10);} var timestamp=Date.now();var date=$("#manager-date-input").datepicker("getDate");if(date){timestamp=parseInt($.datepicker.formatDate("@",date),10);}
dobrado.log("Loading available products...","info");$.post("/php/request.php",{request:"manager",action:"loadProducts",composite:composite,username:user,product:product,timestamp:timestamp,url:location.href,token:dobrado.token},function(response){if(dobrado.checkResponseError(response,"manager loadProducts")){return;} dobrado.log("Loading available products...","info");$.post("/php/request.php",{request:"manager",action:"loadProducts",composite:composite,username:user,product:product,timestamp:timestamp,url:location.href,token:dobrado.token},function(response){if(dobrado.checkResponseError(response,"manager loadProducts")){return;}
var products=JSON.parse(response);var purchaseTotal=0;$.each(products.available,function(index,item){var quantity=0;var currentTime=timestamp;if(products.current[item.name]){quantity=products.current[item.name].quantity;currentTime=products.current[item.name].date;} var productList=JSON.parse(response);var purchaseTotal=0;$.each(productList.available,function(index,item){var quantity=0;var currentTime=timestamp;if(productList.current[item.name]){quantity=productList.current[item.name].quantity;currentTime=productList.current[item.name].date;}
var total=quantity*item[priceLevel];purchaseTotal+=total;allProductsData.push({date:currentTime,name:item.name,supplier:item.user,quantity:quantity,unit:item.unit,price:item[priceLevel].toFixed(2),basePrice:item.price.toFixed(2),total:total.toFixed(2)});});$(".manager-view-all-dialog").dialog("open");if(allProductsGrid){allProductsGrid.setData(allProductsData);allProductsGrid.updateRowCount();allProductsGrid.render();$(allProductsGridId).show();$(allProductsGridId+" .slick-header-columns").children().eq(3).click().click();$(".manager-view-all-total").html("Current total: $"+ var total=quantity*item[priceLevel];purchaseTotal+=total;allProductsData.push({date:currentTime,name:item.name,supplier:item.user,quantity:quantity,unit:item.unit,price:item[priceLevel].toFixed(2),basePrice:item.price.toFixed(2),total:total.toFixed(2)});});if(composite){$(".manager-view-all-dialog").dialog("option","title","Editing items for "+product);}
else{$(".manager-view-all-dialog").dialog("option","title","Available Products");}
$(".manager-view-all-dialog").dialog("open");if(allProductsGrid){allProductsGrid.setData(allProductsData);allProductsGrid.updateRowCount();allProductsGrid.render();$(allProductsGridId).show();$(allProductsGridId+" .slick-header-columns").children().eq(3).click().click();$(".manager-view-all-total").html("Current total: $"+
purchaseTotal.toFixed(2));}});} purchaseTotal.toFixed(2));}});}
function updatePurchase(e,args){var user=$("#manager-username-input").val();var product=$("#manager-product-input").val();var supplier=$("#manager-supplier-input").val();var item=args.item;var purchaseTotal=0;$.each(allProductsData,function(i,data){purchaseTotal+=data.quantity*data.price;});$(".manager-view-all-total").html("Current total: $"+ function updatePurchase(e,args){var user=$("#manager-username-input").val();var product=$("#manager-product-input").val();var supplier=$("#manager-supplier-input").val();var item=args.item;var purchaseTotal=0;$.each(allProductsData,function(i,data){purchaseTotal+=data.quantity*data.price;});$(".manager-view-all-total").html("Current total: $"+
purchaseTotal.toFixed(2));var total=item.quantity*item.price;item.total=total.toFixed(2);if(allProductsGrid){allProductsGrid.invalidate();} purchaseTotal.toFixed(2));var total=item.quantity*item.price;item.total=total.toFixed(2);if(allProductsGrid){allProductsGrid.invalidate();}
......
...@@ -115,6 +115,8 @@ if (!this.dobrado.manager) { ...@@ -115,6 +115,8 @@ if (!this.dobrado.manager) {
$("#manager-quantity-input").spinner({ min: 0, spin: setQuantity, $("#manager-quantity-input").spinner({ min: 0, spin: setQuantity,
change: setQuantity }); change: setQuantity });
$(".manager .toggle-search-options").click(function() { $(".manager .toggle-search-options").click(function() {
clearSearchDates();
clearDate();
$(".manager .search-options").toggle(); $(".manager .search-options").toggle();
}); });
...@@ -919,14 +921,14 @@ if (!this.dobrado.manager) { ...@@ -919,14 +921,14 @@ if (!this.dobrado.manager) {
if (dobrado.checkResponseError(response, "manager loadProducts")) { if (dobrado.checkResponseError(response, "manager loadProducts")) {
return; return;
} }
var products = JSON.parse(response); var productList = JSON.parse(response);
var purchaseTotal = 0; var purchaseTotal = 0;
$.each(products.available, function(index, item) { $.each(productList.available, function(index, item) {
var quantity = 0; var quantity = 0;
var currentTime = timestamp; var currentTime = timestamp;
if (products.current[item.name]) { if (productList.current[item.name]) {
quantity = products.current[item.name].quantity; quantity = productList.current[item.name].quantity;
currentTime = products.current[item.name].date; currentTime = productList.current[item.name].date;
} }
var total = quantity * item[priceLevel]; var total = quantity * item[priceLevel];
purchaseTotal += total; purchaseTotal += total;
...@@ -937,6 +939,14 @@ if (!this.dobrado.manager) { ...@@ -937,6 +939,14 @@ if (!this.dobrado.manager) {
basePrice: item.price.toFixed(2), basePrice: item.price.toFixed(2),
total: total.toFixed(2) }); total: total.toFixed(2) });
}); });
if (composite) {
$(".manager-view-all-dialog").dialog("option", "title",
"Editing items for " + product);
}
else {
$(".manager-view-all-dialog").dialog("option", "title",
"Available Products");
}
$(".manager-view-all-dialog").dialog("open"); $(".manager-view-all-dialog").dialog("open");
if (allProductsGrid) { if (allProductsGrid) {
allProductsGrid.setData(allProductsData); allProductsGrid.setData(allProductsData);
......
...@@ -28,7 +28,7 @@ if(!this.dobrado.purchase){dobrado.purchase={};} ...@@ -28,7 +28,7 @@ if(!this.dobrado.purchase){dobrado.purchase={};}
(function(){'use strict';var purchase=null;var purchaseGrid=null;var purchaseGridId="";var allAvailableGrid=null;var allAvailableGridId="";var allAvailableData=[];var allUserGrid=null;var allUserGridId="";var allUserData=[];var allUserChanges={};var currentProduct=null;var currentWeek=true;var startTime=new Date().getTime();var tomorrow=0;var yesterday=0;var oneDay=86400000;var stockUpdate=0;var orderMode=false;$(function(){if($(".purchase").length===0){return;} (function(){'use strict';var purchase=null;var purchaseGrid=null;var purchaseGridId="";var allAvailableGrid=null;var allAvailableGridId="";var allAvailableData=[];var allUserGrid=null;var allUserGridId="";var allUserData=[];var allUserChanges={};var currentProduct=null;var currentWeek=true;var startTime=new Date().getTime();var tomorrow=0;var yesterday=0;var oneDay=86400000;var stockUpdate=0;var orderMode=false;$(function(){if($(".purchase").length===0){return;}
window.addEventListener("beforeunload",function(event){if(purchase&&purchase.processed&&purchase.processed.length!==0){var message="Please save your orders before leaving the page.";event.returnValue=message;return message;}});$("#purchase-details-form").dialog({autoOpen:false,modal:true,position:{my:"top",at:"top+50",of:"body"},title:"Add User Details",width:400});$("#purchase-details-form .submit").button().click(saveDetails);$(".purchase-all-available-dialog").dialog({autoOpen:false,modal:true,position:{my:"top",at:"top+50",of:"body"},title:"Available Products",width:830,height:520,close:function(){if(allAvailableGrid){allAvailableGrid.gotoCell(0,0);}}});$(".purchase-all-users-dialog").dialog({autoOpen:false,modal:true,position:{my:"top",at:"top+50",of:"body"},width:830,height:500,close:function(){if(allUserGrid){allUserGrid.gotoCell(0,0);}}});$("#purchase-form .view-all").click(viewAll);$(".purchase .save").button({disabled:true}).click(save);$("#purchase-next-week-input").click(nextWeek);$("#purchase-form .remove").button({disabled:true}).click(remove);$("#purchase-form .add").button({disabled:true}).click(add);$("#purchase-name-input").val("").change(function(){setTimeout(function(){showUser();},10);});$("#purchase-product-input").val("").change(function(){setTimeout(function(){showProduct();},10);});$("#purchase-price-input").val("");$("#purchase-date-input").val("").datepicker({dateFormat:dobrado.dateFormat,minDate:0});$("#purchase-quantity-input").val("");$("#purchase-quantity-input").spinner({disabled:true,min:0,spin:setQuantity,change:setQuantity});$("#purchase-form .add-next-week").click(toggleWeek);$(".purchase-save-order-dismiss").button().click(function(){$(".purchase-save-order-confirm").dialog("close");});$(".grid").each(function(index){if(index===0){purchaseGridId="#"+$(this).attr("id");} window.addEventListener("beforeunload",function(event){if(purchase&&purchase.processed&&purchase.processed.length!==0){var message="Please save your orders before leaving the page.";event.returnValue=message;return message;}});$("#purchase-details-form").dialog({autoOpen:false,modal:true,position:{my:"top",at:"top+50",of:"body"},title:"Add User Details",width:400});$("#purchase-details-form .submit").button().click(saveDetails);$(".purchase-all-available-dialog").dialog({autoOpen:false,modal:true,position:{my:"top",at:"top+50",of:"body"},title:"Available Products",width:830,height:520,close:function(){if(allAvailableGrid){allAvailableGrid.gotoCell(0,0);}}});$(".purchase-all-users-dialog").dialog({autoOpen:false,modal:true,position:{my:"top",at:"top+50",of:"body"},width:830,height:500,close:function(){if(allUserGrid){allUserGrid.gotoCell(0,0);}}});$("#purchase-form .view-all").click(viewAll);$(".purchase .save").button({disabled:true}).click(save);$("#purchase-next-week-input").click(nextWeek);$("#purchase-form .remove").button({disabled:true}).click(remove);$("#purchase-form .add").button({disabled:true}).click(add);$("#purchase-name-input").val("").change(function(){setTimeout(function(){showUser();},10);});$("#purchase-product-input").val("").change(function(){setTimeout(function(){showProduct();},10);});$("#purchase-price-input").val("");$("#purchase-date-input").val("").datepicker({dateFormat:dobrado.dateFormat,minDate:0});$("#purchase-quantity-input").val("");$("#purchase-quantity-input").spinner({disabled:true,min:0,spin:setQuantity,change:setQuantity});$("#purchase-form .add-next-week").click(toggleWeek);$(".purchase-save-order-dismiss").button().click(function(){$(".purchase-save-order-confirm").dialog("close");});$(".grid").each(function(index){if(index===0){purchaseGridId="#"+$(this).attr("id");}
if(index===1){allAvailableGridId="#"+$(this).attr("id");} if(index===1){allAvailableGridId="#"+$(this).attr("id");}
if(index===2){allUserGridId="#"+$(this).attr("id");}});if($(".grid").length!==0){$(".grid").hide();var purchaseColumns=[{id:"product",name:"Product",field:"name",width:210},{id:"supplier",name:"Supplier",field:"supplier",width:140},{id:"date",name:"Date",field:"date",width:110,formatter:Slick.Formatters.Timestamp},{id:"quantity",name:"Quantity",field:"quantity",width:100},{id:"price",name:"Price",field:"price",width:100,formatter:Slick.Formatters.Dollar},{id:"total",name:"Total",field:"total",width:80,formatter:Slick.Formatters.Dollar}];var purchaseOptions={enableColumnReorder:false,forceFitColumns:true};purchaseGrid=dobrado.grid.instance(purchaseGridId,[],purchaseColumns,purchaseOptions);purchaseGrid.setSelectionModel(new Slick.RowSelectionModel());purchaseGrid.onClick.subscribe(function(e,item){showPurchase(item.row);});if($(".grid").length>=2){var allAvailableColumns=[{id:"product",name:"Product",field:"name",width:210,sortable:true},{id:"supplier",name:"Supplier",field:"supplier",width:140,sortable:true},{id:"date",name:"Date",field:"date",width:110,sortable:true,formatter:Slick.Formatters.Timestamp,editor:Slick.Editors.Date},{id:"quantity",name:"Quantity",field:"quantity",width:100,sortable:true,editor:Slick.Editors.Number},{id:"price",name:"Price",field:"price",width:100,sortable:true,formatter:Slick.Formatters.Units},{id:"total",name:"Total",field:"total",width:80,sortable:true,formatter:Slick.Formatters.Dollar}];var allAvailableOptions={editable:true,enableColumnReorder:false,forceFitColumns:true};$(allAvailableGridId).appendTo($(".purchase-all-available-dialog"));allAvailableGrid=dobrado.grid.instance(allAvailableGridId,[],allAvailableColumns,allAvailableOptions);allAvailableGrid.setSelectionModel(new Slick.RowSelectionModel());allAvailableGrid.onClick.subscribe(function(e,item){showAllAvailablePurchase(item.row);});allAvailableGrid.onCellChange.subscribe(updateAvailablePurchaseData);allAvailableGrid.onSort.subscribe(function(e,args){allAvailableData.sort(function(row1,row2){var field=args.sortCol.field;var sign=args.sortAsc?1:-1;var value1=row1[field];var value2=row2[field];if(field!=="name"&&field!=="supplier"){value1=parseFloat(value1);value2=parseFloat(value2);} if(index===2){allUserGridId="#"+$(this).attr("id");}});if($(".grid").length!==0){$(".grid").hide();var purchaseColumns=[{id:"product",name:"Product",field:"name",width:210},{id:"supplier",name:"Supplier",field:"supplier",width:140},{id:"date",name:"Date",field:"date",width:110,formatter:Slick.Formatters.Timestamp},{id:"quantity",name:"Quantity",field:"quantity",width:100},{id:"price",name:"Price",field:"price",width:100,formatter:Slick.Formatters.Dollar},{id:"total",name:"Total",field:"total",width:80,formatter:Slick.Formatters.Dollar}];var purchaseOptions={enableColumnReorder:false,forceFitColumns:true};purchaseGrid=dobrado.grid.instance(purchaseGridId,[],purchaseColumns,purchaseOptions);purchaseGrid.setSelectionModel(new Slick.RowSelectionModel());purchaseGrid.onClick.subscribe(function(e,item){showPurchase(item.row);});purchaseGrid.onSelectedRowsChanged.subscribe(function(e,item){if(item.rows.length===1){showPurchase(item.rows[0]);}});if($(".grid").length>=2){var allAvailableColumns=[{id:"product",name:"Product",field:"name",width:210,sortable:true},{id:"supplier",name:"Supplier",field:"supplier",width:140,sortable:true},{id:"date",name:"Date",field:"date",width:110,sortable:true,formatter:Slick.Formatters.Timestamp,editor:Slick.Editors.Date},{id:"quantity",name:"Quantity",field:"quantity",width:100,sortable:true,editor:Slick.Editors.Number},{id:"price",name:"Price",field:"price",width:100,sortable:true,formatter:Slick.Formatters.Units},{id:"total",name:"Total",field:"total",width:80,sortable:true,formatter:Slick.Formatters.Dollar}];var allAvailableOptions={editable:true,enableColumnReorder:false,forceFitColumns:true};$(allAvailableGridId).appendTo($(".purchase-all-available-dialog"));allAvailableGrid=dobrado.grid.instance(allAvailableGridId,[],allAvailableColumns,allAvailableOptions);allAvailableGrid.setSelectionModel(new Slick.RowSelectionModel());allAvailableGrid.onClick.subscribe(function(e,item){showAllAvailablePurchase(item.row);});allAvailableGrid.onSelectedRowsChanged.subscribe(function(e,item){if(item.rows.length===1){showAllAvailablePurchase(item.rows[0]);}});allAvailableGrid.onCellChange.subscribe(updateAvailablePurchaseData);allAvailableGrid.onSort.subscribe(function(e,args){allAvailableData.sort(function(row1,row2){var field=args.sortCol.field;var sign=args.sortAsc?1:-1;var value1=row1[field];var value2=row2[field];if(field!=="name"&&field!=="supplier"){value1=parseFloat(value1);value2=parseFloat(value2);}
if(value1===value2){return 0;} if(value1===value2){return 0;}
if(value1>value2){return sign;} if(value1>value2){return sign;}
else{return sign* -1;}});allAvailableGrid.invalidate();});} else{return sign* -1;}});allAvailableGrid.invalidate();});}
......
...@@ -184,6 +184,11 @@ if (!this.dobrado.purchase) { ...@@ -184,6 +184,11 @@ if (!this.dobrado.purchase) {
purchaseGrid.onClick.subscribe(function(e, item) { purchaseGrid.onClick.subscribe(function(e, item) {
showPurchase(item.row); showPurchase(item.row);
}); });
purchaseGrid.onSelectedRowsChanged.subscribe(function(e, item) {
if (item.rows.length === 1) {
showPurchase(item.rows[0]);
}
});
// If a second grid module is on the page initialise columns to view // If a second grid module is on the page initialise columns to view
// all available products. // all available products.
...@@ -217,6 +222,11 @@ if (!this.dobrado.purchase) { ...@@ -217,6 +222,11 @@ if (!this.dobrado.purchase) {
allAvailableGrid.onClick.subscribe(function(e, item) { allAvailableGrid.onClick.subscribe(function(e, item) {
showAllAvailablePurchase(item.row); showAllAvailablePurchase(item.row);
}); });
allAvailableGrid.onSelectedRowsChanged.subscribe(function(e, item) {
if (item.rows.length === 1) {
showAllAvailablePurchase(item.rows[0]);
}
});
allAvailableGrid.onCellChange.subscribe(updateAvailablePurchaseData); allAvailableGrid.onCellChange.subscribe(updateAvailablePurchaseData);
allAvailableGrid.onSort.subscribe(function (e, args) { allAvailableGrid.onSort.subscribe(function (e, args) {
allAvailableData.sort(function(row1, row2) { allAvailableData.sort(function(row1, row2) {
......
This diff is collapsed.
...@@ -51,6 +51,10 @@ if (!this.dobrado.stock) { ...@@ -51,6 +51,10 @@ if (!this.dobrado.stock) {
var currentProduct = null; var currentProduct = null;
// Allow showing available products only. // Allow showing available products only.
var showAvailable = false; var showAvailable = false;
// Remember the last product saved during import to check for duplicates.
var lastProductSaved = "";
// Stop submit function being called again before it returns.
var saving = false;
$(function() { $(function() {
// Don't run if the module isn't on the page. // Don't run if the module isn't on the page.
...@@ -178,14 +182,14 @@ if (!this.dobrado.stock) { ...@@ -178,14 +182,14 @@ if (!this.dobrado.stock) {
// quantity adjustments. // quantity adjustments.
if ($(".grid").length === 2 && stock.trackQuantity) { if ($(".grid").length === 2 && stock.trackQuantity) {
var adjustmentColumns = var adjustmentColumns =
[ { id: "product", name: "Product", field: "name", width: 220, [ { id: "product", name: "Product", field: "name", width: 200,
sortable: true }, sortable: true },
{ id: "supplier", name: "Supplier", field: "supplier", { id: "supplier", name: "Supplier", field: "supplier",
width: 140, sortable: true }, width: 130, sortable: true },
{ id: "date", name: "Date", field: "date", width: 110, { id: "date", name: "Date", field: "date", width: 110,
sortable: true, formatter: Slick.Formatters.Timestamp }, sortable: true, formatter: Slick.Formatters.Timestamp },
{ id: "adjustment", name: "Total", field: "adjustment", { id: "adjustment", name: "Adjustment", field: "adjustment",
width: 90, sortable: true }]; width: 120, sortable: true }];
var adjustmentOptions = { var adjustmentOptions = {
enableColumnReorder: false, enableColumnReorder: false,
forceFitColumns: true forceFitColumns: true
...@@ -401,6 +405,7 @@ if (!this.dobrado.stock) { ...@@ -401,6 +405,7 @@ if (!this.dobrado.stock) {
$.isNumeric(price) && size !== currentProduct.size) { $.isNumeric(price) && size !== currentProduct.size) {
var newPrice = currentProduct.size / size * price; var newPrice = currentProduct.size / size * price;
$("#stock-price-input").val(newPrice.toFixed(2)); $("#stock-price-input").val(newPrice.toFixed(2));
currentProduct.size = size;
} }
// Need to always update wholesale and retail prices because they don't // Need to always update wholesale and retail prices because they don't
// get pulled from the import data. // get pulled from the import data.
...@@ -551,7 +556,6 @@ if (!this.dobrado.stock) { ...@@ -551,7 +556,6 @@ if (!this.dobrado.stock) {
} }
var data = adjustmentData[row]; var data = adjustmentData[row];
$("#stock-quantity-adjust-input").val(data.adjustment);
$("#stock-quantity-reason-input").val(data.description); $("#stock-quantity-reason-input").val(data.description);
} }
...@@ -601,7 +605,24 @@ if (!this.dobrado.stock) { ...@@ -601,7 +605,24 @@ if (!this.dobrado.stock) {
} }
function submit() { function submit() {
// Don't allow submit to be called more than once before returning.
if (saving) {
return false;
}
var name = $("#stock-name-input").val(); var name = $("#stock-name-input").val();
if (name === "") {
return false;
}
// Want to check for submitting duplicate rows during import, which exist
// due to half boxes. Just ask the user to confirm the second entry.
if (name === lastProductSaved) {
if (!confirm("This product was just saved, continue?")) {
showImportData(false);
return false;