Odoo 8 , how to convert an existing Quotation to Sales order via XMLRPC - odoo-8

1] I have already created a Quotation in Odoo 8 Setup via XMLRPC :
return_id = api.execute_kw(db, uid, pwd, 'sale.order','create',[{'note':'******~~~~~********','state':'draft','order_policy':'manual','amount_tax':0.0,'amount_untaxed':0.0,'amount_total':0.0,'partner_invoice_id':22, 'partner_shipping_id':22}])
2] AND then added an order line too to this quotation :
return_id = api.execute_kw(db, uid, pwd,'sale.order.line','create', [{ 'product_id':2,'product_uos_quantity':1.000, 'order_id':37, 'quantity':1 }]);
Now what I need is to further convert this quotation to sales order via XMLRPC so that it stimulates all the normal 'confirm sale' button actions like logging message, converting quotation to sales order and making all necessary changes in all the required tables.

You will confirm sale order by xmlrpc using below code. Here sale_order_id is the id of the sale order, that you get when creating the sale order. By executing code, the Quotation convert into sale order.
api.exec_workflow(db, uid, password, 'sale.order', 'order_confirm', sale_order_id)

Related

How to add filter on item collection to get the Sales rep(total Quantity and Total no of Orders) of those Sale Managers which are logged in

$collection = $this->_itemCollectionFactory->create()->getCollection();
$collection->getSelect()->columns(array('total_orders' => new \Zend_Db_Expr('COUNT(order_id)')))
->columns(array('total_qty' => new \Zend_Db_Expr('ROUND(SUM(qty_ordered))')))
->group('sku');
$collection->getSelect()->limit(3);
$collection->addFieldToFilter('store_id', 2);
Through this code i can get the total quantity and total number of orders of all sales rep. But i need only those total quantity and total orders which were done by the Sales Rep og Logged in Sale Manager.
As you mentioned in your question you only want to get the order info based on a certain sales rep. To do that you need to somehow find a unique identify for the currently logged in sales rep and add a filter for that .
For example:
$collection = $this->_itemCollectionFactory->create()->getCollection();
$collection->getSelect()->columns(array('total_orders' => new \Zend_Db_Expr('COUNT(order_id)')))
->columns(array('total_qty' => new \Zend_Db_Expr('ROUND(SUM(qty_ordered))')))
->group('sku');
$collection->getSelect()->limit(3);
$collection->addFieldToFilter('store_id', 2);
$collection->addFieldToFilter('sales_rep_identifier', $loggedInSalesRepIdentifier);
The label sales_rep_identifier and the value $loggedInSalesRepIdentifier are just examples, you may have to adjust the format in which the data is stored if it doesn't currently have a field to check natively what sales rep did it, and adjust the values there accordingly
If you're using some kind of prebuilt system then maybe there are other labels for the identifier you could use, without more information on the specific database structure it's impossible to answer exactly, but essentially you need to filter by the unique sales rep identifier, and if that doesn't exist now in the database it should somehow but added

Xeroizer::ApiException : QueryParseException: No property or field 'inv_id' exists

I am Trying to get all the invoices in a single API hit.
Because, for every user having 100's of invoices.
It will exceed the API limit (Minute Limit: 60 calls in a rolling 60 second window).
I am trying to store all the invoice id into a single array and from that i will get the details of the user and then i loop the records locally and display it. It's the right way?
invoice_ids = user.estimates.select("invoice_id") || [] xero = Xeroizer::PrivateApplication.new(XERO_CONFIG["key"], XERO_CONFIG["secret"], XERO_CONFIG["path"], :rate_limit_sleep => 5)
invoices = ['795f789b-5958-xxxx-yyyy-48436dbe7757','987g389b-5958-xxxx-yyyy-68636dbe5589']
inv_id = invoice_ids.pluck(:invoice_id)
invoices = xero.Invoice.all(:where => 'InvoiceID==inv_id')
Also, I am getting the following error:
Xeroizer::ApiException (QueryParseException: No property or field 'inv_id' exists in type 'Invoice')
Looks like the problem is that you're not interpolating the inv_ids correctly. You probably need to do something like this:
invoices = xero.Invoice.all(:where => "InvoiceID==\"#{inv_id}\"")
You may have to perform some additional formatting on the inv_id variable to make it a valid Xero string. https://github.com/waynerobinson/xeroizer#retrieving-data

Prevent Available stock become minus

It's possible that in Adempiere, Inventory Stock become negative. One of the way to make it become negative is when we put Quantity in Internal Use Inventory more than Available Stock in Warehouse.
Example
Product Info
------------
Product || Qty
Fertilizer || 15
It's shown in Product Info that the current Qty of Fertilizer is 15. Then I make Internal Use Inventory document
Internal Use Inventory
----------------------
Product || Qty
Fertilizer || 25
When I complete it, Quantity will be -10. How can I prevent Internal Use Inventory being completed when Quantity is more than Available Stock so that I can avoid negative stock ?
This is purposely designed functionality of Adempiere. Under some scenarios the Inventory is allowed to become negative because it is felt in those scenarios it is better to allow the process to complete but being negative it highlights a problem that must be addressed. In the case of the Internal Use the user is warned, that the stock will go negative if they proceed.
To change this standard functionality you need to modify the
org.compiere.model.MInventory.completeIt()
But if you change the code directly, it will make it more difficult to keep your version in sync with the base Adempiere or even just applying patches.
The recommended approach would be to add a Model Validator. This is a mechanism that watches the underlying data model and enables additional code/logic to be injected when a specific event occurs.
The event you want is the Document Event TIMING_BEFORE_COMPLETE.
You would create a new model validator as described in the link, register it in Adempiere's Application Dictionary and since you want your code to trigger when Inventory Document Type is executed you would add a method something like this
public String docValidate (PO po, int timing)
{
if (timing == TIMING_BEFORE_COMPLETE) {
if (po.get_TableName().equals(MInventory.Table_Name))
{
// your code to be executed
// it is executed just before any (internal or physical)
// Inventory is Completed
}
}
return null;
} // docValidate
A word of warning; the Internal Use functionality is the same used by Physical Inventory (i.e. a stock count) functionality! They just have different windows in Adempiere. So be sure to test both functionalities after any change is applied. From the core org.compiere.model.MInventory there is a hint as how you might differentiate the two.
//Get Quantity Internal Use
BigDecimal qtyDiff = line.getQtyInternalUse().negate();
//If Quantity Internal Use = Zero Then Physical Inventory Else Internal Use Inventory
if (qtyDiff.signum() == 0)
In order to prevent the stock from being negative you can use two methods
Callout in Code
BeforeSave Method
In order to apply it in Callout you need to create a Callout class and get the current Stock Qty at the locator there and then subtract the qty from entered Qty and if the result is less than 0 , display the error. Apply this on the Qty field and you will get the desired result.
This is slightly better way , as this doesn't needs creating a new class in code altogether and will consume less memory altogether , Search for MInventoryLine class in code and then search for beforesave() in it. Add the same code (getting the stock and then subtracting it from the entered Qty). The Code in beforesave() will be like this
if (your condition here) { log.saveError("Could Not Save - Error", "Qty less than 0"); return false; }
Now I am assuming that you know the basic code to create a Callout and design a condition, If you need any help , let me know.
Adding to the answer of Mr. Colin, please see the below code to restrict the negative inventory from the M_Inventory based transaction. You can consider the same concept in M_Inout and M_Movement Tables also.
for (MInventoryLine line : mInventory.getLines(true))
{
String blockNegativeQty = MSysConfig.getValue("BLOCK_NEGATIVE_QUANTITY_IN_MATERIAL_ISSUE","Y", getAD_Client_ID());
if(blockNegativeQty.equals("Y"))
{
//Always check the on Hand Qty not Qty Book Value. The old Drafted Qty Book Value may be changed alredy.
String sql = "SELECT adempiere.bomqtyonhand(?, ?, ?)";
BigDecimal onhandQty = DB.getSQLValueBD(line.get_TrxName(), sql, line.getM_Product_ID(), mInventory.getM_Warehouse_ID()
, line.getM_Locator_ID());
BigDecimal QtyMove = onhandQty.subtract(line.getQtyInternalUse());
if(QtyMove.compareTo(Env.ZERO) < 0)
{
log.warning("Negative Movement Quantity is restricted. Qty On Hand = " + onhandQty
+ " AND Qty Internal Use = " + line.getQtyInternalUse()
+ ". The Movement Qty is = " + QtyMove);
negativeCount ++;
negativeProducts = negativeProducts + line.getM_Product().getName() + ": " + onhandQty + " ; ";
}
}
}
if(negativeCount > 0)
{
m_processMsg = "Negative Inventory Restricted. "
+ " Restriction has been enabled through the client level system configurator."
+ " Products : " + negativeProducts;
}
return m_processMsg;

How to get quote_id from sales order page of admin in magento?

Is it possible to get quote_id of an specific order in admin->sales->orders->view(select particular order) page ?
I want to show my custom table(which contain quote_id for an order) data in admin->sales->view(select particular order) gift option block.
Yes, the order itself has quote_id, you can retrieve it in this way:
// supposing order id is 1
$order = Mage::getModel('sales/order')->load(1);
$quoteId = $order->getQuoteId();
if you need to retrieve quote object, you can get it by:
$quoteObject = Mage::getModel('sales/quote')->load($quoteId);

Facebook API: Getting photos that have a comment containing a a string

I'm implementing a pseudo hash-tagging system for the company I work at with their customer's facebook photos. A customer can upload a photo to the page, and a page admin can tag it with the hashtag for a product.
What I am trying to do is get all photos from the page that have a certain tag in the comments (for instance, get all photos from the company page with a comment containing only '#bluepants').
I am trying to make sure the Facebook API handles the heavy lifting (we'll cache the results), so I'd like to use FQL or the Graphs API, but I can't seem to get it working (my SQL is quite rusty after relying on an ORM for so long). I would prefer if it outputs as many results as possible, but I'm not sure if FB lets you do more than 25 at once.
This is going to be implemented in a sinatra site (I am currently playing around with the Koala gem, so bonus points if I can query using it)
Could anyone give me some guidance?
Thanks!
I've got something like this working in FQL/PHP. Here is my multiquery.
{'activity':
"SELECT post_id, created_time FROM stream WHERE source_id = PAGE_ID AND
attachment.fb_object_type = 'photo' AND created_time > 1338834720
AND comments.count > 0 LIMIT 0, 500",
'commented':
"SELECT post_id, text, fromid FROM comment WHERE post_id IN
(SELECT post_id FROM #activity) AND AND (strpos(upper(text), '#HASHTAG') >= 0",
'accepted':
"SELECT post_id, actor_id, message, attachment, place, created_time, likes
FROM stream WHERE post_id IN (SELECT post_id FROM #commented)
ORDER BY likes.count DESC",
'images':
"SELECT pid, src, src_big, src_small, src_width, src_height FROM photo
WHERE pid IN (SELECT attachment.media.photo.pid FROM #accepted)",
'users':
"SELECT name, uid, current_location, locale FROM user WHERE uid IN
(SELECT actor_id FROM #accepted)",
'pages':
"SELECT name, page_id FROM page WHERE page_id IN (SELECT actor_id FROM #accepted)",
'places':
"SELECT name, page_id, description, display_subtext, latitude, longitude
FROM place WHERE page_id IN (SELECT place FROM #accepted)"
}
To break this down:
#activity gets all stream objects created after the start date of my campaign that are photos and have a non-zero comment count. Using a LIMIT of 500 seems to return the maximum number of posts. Higher or lower values return fewer.
#commented finds the posts that have #HASHTAG in the text of one of their comments. Note, I'm not looking for a #, which is a reserved character in FQL. Using it may cause you problems.
#accepted gets the full details of the posts found in #commented.
#images gets all the details of the images in those posts. I have it on my todos to refactor this to use object_id instead of pid and try using the new real_width specification to make my layout easier.
#users and #pages get the details of the actor who originally posted the item. I now know I could have used the profile table to get this in one query.
#places gets the location details for geo-tagged posts.
You can see this in action here: http://getwellgabby.org/show-us-a-sign

Resources