Commit a15908ef by Damien Moulard

create product orders in odoo

parent 6a661024
...@@ -222,6 +222,81 @@ class Order(models.Model): ...@@ -222,6 +222,81 @@ class Order(models.Model):
labels_data['total'] += l['product_qty'] labels_data['total'] += l['product_qty']
return labels_data return labels_data
def get_order_attachment_id(self):
res = {}
f = ["id"]
c = [['res_model', '=', 'purchase.order'], ['res_id', '=', self.id], ['type', 'in', ['binary', 'url']]]
try:
attachment = self.o_api.search_read('ir.attachment', c, f)
res = attachment[0]
except Exception as e:
res["id_po"] = self.id
res["error"] = str(e)
return res
@staticmethod
def create(supplier_id, date_planned, order_lines):
order_data = {
"partner_id": int(supplier_id),
"partner_ref": False,
"currency_id": 1,
"date_order": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"origin": "Aide à la commande",
"company_id": 1,
"order_line": [],
"notes": False,
"date_planned": date_planned,
"picking_type_id": 1,
"dest_address_id": False,
"incoterm_id": False,
"payment_term_id": False,
"fiscal_position_id": False,
"message_follower_ids": False,
"message_ids": False
}
for line in order_lines:
order_data["order_line"].append(
[
0,
False,
{
"package_qty": line["package_qty"],
"price_policy": "uom",
"indicative_package": True,
"product_id": line["product_variant_ids"][0],
"name": line["name"],
"date_planned": date_planned,
"account_analytic_id": False,
"product_qty_package":line["product_qty_package"],
"product_qty": line["product_qty"],
"product_uom": line["product_uom"],
"price_unit": line["price_unit"],
"discount": 0,
"taxes_id": [
[
6,
False,
line["supplier_taxes_id"]
]
]
}
]
)
api = OdooAPI()
id_po = api.create('purchase.order', order_data)
res_confirm = api.execute('purchase.order', 'button_confirm', [id_po])
res = {
'id_po': id_po,
'confirm_po': True
}
return res
class Orders(models.Model): class Orders(models.Model):
@staticmethod @staticmethod
......
...@@ -72,14 +72,20 @@ ...@@ -72,14 +72,20 @@
right: 0; right: 0;
} }
/* -- Supplier form */ /* -- Order data */
#supplier_form_container { #order_data_container {
margin-top: 30px; margin-top: 30px;
display: flex;
justify-content: space-evenly;
} }
#supplier_input { #supplier_input {
width: 500px; width: 350px;
margin-right: 10px; border-radius: 5px;
}
#date_planned_input {
margin-left: 40px;
border-radius: 5px; border-radius: 5px;
} }
...@@ -89,7 +95,9 @@ ...@@ -89,7 +95,9 @@
} }
#products_table_filter input{ #products_table_filter input{
height: 40px; height: 35px;
width: 300px;
border-radius: 10px;
} }
#table_header_select_all{ #table_header_select_all{
...@@ -125,6 +133,14 @@ ...@@ -125,6 +133,14 @@
cursor: pointer; cursor: pointer;
} }
/* -- Bottom action button */
#orders_creation_area {
display: flex;
justify-content: space-between;
margin: 15px 0 35px 0;
}
/* -- Suppliers list */ /* -- Suppliers list */
#suppliers_container { #suppliers_container {
display: flex; display: flex;
...@@ -142,4 +158,55 @@ ...@@ -142,4 +158,55 @@
color: red; color: red;
margin-left: 5px; margin-left: 5px;
cursor: pointer; cursor: pointer;
}
/* - Orders created screen */
.order_created_header {
margin-top: 15px;
margin-bottom: 40px;
}
#created_orders_area {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
}
.new_order_item {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 20px;
}
.download_order_file {
margin-top: 10px;
}
.download_order_file_button:hover {
text-decoration: none;
color: white;
}
#recap_delivery_date {
font-weight: bold;
}
.mail_example_container {
display: flex;
flex-direction: column;
align-items: center;
width: 30%;
margin: 0 auto;
}
.mail_type_text {
width: 100%;
}
.mail_example {
background-color: #e7e9ed;
width: 100%;
padding: 15px;
} }
\ No newline at end of file
...@@ -13,4 +13,6 @@ urlpatterns = [ ...@@ -13,4 +13,6 @@ urlpatterns = [
url(r'^get_suppliers$', views.get_suppliers), url(r'^get_suppliers$', views.get_suppliers),
url(r'^get_supplier_products$', views.get_supplier_products), url(r'^get_supplier_products$', views.get_supplier_products),
url(r'^associate_supplier_to_product$', views.associate_supplier_to_product), url(r'^associate_supplier_to_product$', views.associate_supplier_to_product),
url(r'^create_orders$', views.create_orders),
url(r'^get_orders_attachment$', views.get_orders_attachment),
] ]
...@@ -7,6 +7,7 @@ from products.models import CagetteProduct, CagetteProducts ...@@ -7,6 +7,7 @@ from products.models import CagetteProduct, CagetteProducts
from openpyxl import Workbook from openpyxl import Workbook
from openpyxl.writer.excel import save_virtual_workbook from openpyxl.writer.excel import save_virtual_workbook
import datetime
def as_text(value): return str(value) if value is not None else "" def as_text(value): return str(value) if value is not None else ""
...@@ -17,7 +18,8 @@ def helper(request): ...@@ -17,7 +18,8 @@ def helper(request):
context = { context = {
'title': 'Aide à la commande', 'title': 'Aide à la commande',
'couchdb_server': settings.COUCHDB['url'], 'couchdb_server': settings.COUCHDB['url'],
'db': settings.COUCHDB['dbs']['orders'] 'db': settings.COUCHDB['dbs']['orders'],
'odoo_server': settings.ODOO['url']
} }
template = loader.get_template('orders/helper.html') template = loader.get_template('orders/helper.html')
...@@ -59,6 +61,48 @@ def associate_supplier_to_product(request): ...@@ -59,6 +61,48 @@ def associate_supplier_to_product(request):
return JsonResponse({'res': res}) return JsonResponse({'res': res})
def create_orders(request):
""" Create products orders """
res = { "created": [] }
try:
data = json.loads(request.body.decode())
# suppliers id are keys in request data
for supplier_id in data["suppliers_data"].keys():
res_created = Order.create(supplier_id, data["date_planned"], data["suppliers_data"][supplier_id])
res_created["supplier_id"] = supplier_id
res["created"].append(res_created)
except Exception as e:
res["error"] = str(e)
return JsonResponse(res, status=500)
return JsonResponse({'res': res})
def get_orders_attachment(request):
""" Get order attachment: order file created after PO is finalized """
res = []
po_ids = request.GET.getlist('po_ids')
for id_po in po_ids:
m = Order(int(id_po))
attachment = m.get_order_attachment_id()
if 'error' in attachment:
res.append(attachment)
else:
res.append({
'id_po': id_po,
'id_attachment': attachment["id"]
})
for item in res:
if 'error' in item:
return JsonResponse(res, status=500)
return JsonResponse({'res': res})
def export_one(request, oid): def export_one(request, oid):
msg = '' msg = ''
try: try:
...@@ -66,7 +110,6 @@ def export_one(request, oid): ...@@ -66,7 +110,6 @@ def export_one(request, oid):
order = Order(oid) order = Order(oid)
order_data = order.export() order_data = order.export()
if ('success' in order_data) and (order_data['success'] is True): if ('success' in order_data) and (order_data['success'] is True):
import datetime
now = datetime.datetime.now() now = datetime.datetime.now()
taxes = 0 taxes = 0
company_name = '' company_name = ''
......
...@@ -436,7 +436,7 @@ class CagetteProducts(models.Model): ...@@ -436,7 +436,7 @@ class CagetteProducts(models.Model):
today = datetime.date.today().strftime("%Y-%m-%d") today = datetime.date.today().strftime("%Y-%m-%d")
# Get products/supplier relation # Get products/supplier relation
f = ["product_tmpl_id", 'date_start', 'date_end', 'package_qty'] f = ["product_tmpl_id", 'date_start', 'date_end', 'package_qty', 'price']
c = [['name', '=', int(supplier_id)]] c = [['name', '=', int(supplier_id)]]
psi = api.search_read('product.supplierinfo', c, f) psi = api.search_read('product.supplierinfo', c, f)
...@@ -449,21 +449,30 @@ class CagetteProducts(models.Model): ...@@ -449,21 +449,30 @@ class CagetteProducts(models.Model):
ptids.append(p["product_tmpl_id"][0]) ptids.append(p["product_tmpl_id"][0])
# Get products templates # Get products templates
f = ["id", "state", "name", "default_code", "qty_available", "incoming_qty", "uom_id", "purchase_ok"] f = [
# TODO fetch only 'purchase_ok' products ? "id",
"state",
"name",
"default_code",
"qty_available",
"incoming_qty",
"uom_id",
"purchase_ok",
"supplier_taxes_id",
"product_variant_ids"
]
c = [['id', 'in', ptids], ['purchase_ok', '=', True]] c = [['id', 'in', ptids], ['purchase_ok', '=', True]]
products_t = api.search_read('product.template', c, f) products_t = api.search_read('product.template', c, f)
filtered_products_t = [p for p in products_t if p["state"] != "end" and p["state"] != "obsolete"] filtered_products_t = [p for p in products_t if p["state"] != "end" and p["state"] != "obsolete"]
# Add package qty to product data # Add supplier data to product data
for i, fp in enumerate(filtered_products_t): for i, fp in enumerate(filtered_products_t):
psi_item = next(item for item in psi if item["product_tmpl_id"] is not False and item["product_tmpl_id"][0] == fp["id"]) psi_item = next(item for item in psi if item["product_tmpl_id"] is not False and item["product_tmpl_id"][0] == fp["id"])
filtered_products_t[i]['supplierinfo'] = { filtered_products_t[i]['suppliersinfo'] = [{
'supplier_id': supplier_id, 'supplier_id': int(supplier_id),
'package_qty': psi_item["package_qty"] 'package_qty': psi_item["package_qty"],
} 'price': psi_item["price"]
}]
# Note: if product.product is needed, get "product_variant_ids" from product template
res["products"] = filtered_products_t res["products"] = filtered_products_t
except Exception as e: except Exception as e:
......
...@@ -24,17 +24,19 @@ ...@@ -24,17 +24,19 @@
</form> </form>
</div> </div>
<div id="existing_orders_area"> <div id="existing_orders_area">
<h2>Ou, continuer une commande existante</h2> <h2>Ou, continuer une commande en cours de création</h2>
<div id="existing_orders"></div> <div id="existing_orders"></div>
</div> </div>
</div> </div>
<div id="main_content" class="page_content" style="display:none;"> <div id="main_content" class="page_content" style="display:none;">
<div id="back_to_order_selection"> <div id="back_to_order_selection_from_main">
<button type="button" class="btn--danger"><i class="fas fa-arrow-left"></i>&nbsp; Retour</button> <button type="button" class="btn--danger"><i class="fas fa-arrow-left"></i>&nbsp; Retour</button>
</div> </div>
<div id="actions_buttons_area"> <div id="actions_buttons_area">
<button type="button" class='btn--primary' id="do_inventory">Faire un inventaire</button> <button type="button" class='btn--primary' id="do_inventory" style="display:none;">
Faire un inventaire
</button>
</div> </div>
<div class="header txtcenter"> <div class="header txtcenter">
...@@ -42,11 +44,12 @@ ...@@ -42,11 +44,12 @@
<i>Commande : <span class="order_name_container"></span></i> <i>Commande : <span class="order_name_container"></span></i>
</div> </div>
<div class="txtcenter" id="supplier_form_container"> <div class="txtcenter" id="order_data_container">
<form action="javascript:;" id="supplier_form"> <form action="javascript:;" id="supplier_form">
<input type="text" name="supplier" id="supplier_input" placeholder="Rechercher un fournisseur par son nom"> <input type="text" name="supplier" id="supplier_input" placeholder="Rechercher un fournisseur par son nom">
<button type="submit" class='btn--primary'>Ajouter le fournisseur</button> <button type="submit" class='btn--primary'>Ajouter le fournisseur</button>
</form> </form>
<input type="text" name="date_planned" id="date_planned_input" placeholder="Date de livraison souhaitée">
</div> </div>
<div class="txtcenter" id="suppliers_container"></div> <div class="txtcenter" id="suppliers_container"></div>
...@@ -56,6 +59,40 @@ ...@@ -56,6 +59,40 @@
<table id="products_table" class="display" cellspacing="0" width="100%"></table> <table id="products_table" class="display" cellspacing="0" width="100%"></table>
</div> </div>
</div> </div>
<div id="orders_creation_area">
<div class="add_product_container"></div>
<button type="button" class='btn--primary' id="create_orders" style="display:none;">
Générer les commandes
</button>
</div>
</div>
<div id="orders_created" class="page_content" style="display:none;">
<div id="back_to_order_selection_from_orders_created">
<button type="button" class="btn--danger"><i class="fas fa-arrow-left"></i>&nbsp; Retour</button>
</div>
<div class="order_created_header txtcenter">
<h2>Commandes créées !</h2>
</div>
<div class="txtcenter">
Livraison prévue le : <span id="recap_delivery_date">XX/XX/XX</span>
</div>
<div id="created_orders_area"></div>
<br/><br/><hr/><br/>
<div class="mail_example_container">
<p class="mail_type_text">Mail type :</p>
<div class="mail_example">
Objet : Cde Cagette JJ/MM<br/>
<br/>
Bonjour XXXXXXX,<br/>
<br/>
Voici la commande de La Cagette pour le XX/XX/XX.<br/>
<br/>
Merci d'avance,<br/>
Bonne journée
</div>
</div>
</div> </div>
<div id="templates" style="display:none;"> <div id="templates" style="display:none;">
...@@ -74,6 +111,19 @@ ...@@ -74,6 +111,19 @@
</div> </div>
</div> </div>
<div id="new_order_item_template">
<div class="new_order_item">
<h3 class="new_order_supplier_name"></h3>
<h3 class="new_order_po"></h3>
<div class='download_order_file'>
<i class="fas fa-spinner fa-spin download_order_file_loading"></i>
<a class='btn--success download_order_file_button' style="display:none;" href="#">
Télécharger le fichier de commande
</a>
</div>
</div>
</div>
<div id="modal_order_access"> <div id="modal_order_access">
<h3>Attention !</h3> <h3>Attention !</h3>
<br/> <br/>
...@@ -126,6 +176,15 @@ ...@@ -126,6 +176,15 @@
<p>Êtez-vous sûr ?</p> <p>Êtez-vous sûr ?</p>
<hr/> <hr/>
</div> </div>
<div id="modal_create_order">
<h3>Attention !</h3>
<p>
Vous vous apprêtez à générer les commandes à partir des données rentrées dans le tableau.
</p>
<p>Êtez-vous sûr ?</p>
<hr/>
</div>
</div> </div>
</div> </div>
...@@ -134,6 +193,7 @@ ...@@ -134,6 +193,7 @@
<script type="text/javascript"> <script type="text/javascript">
var couchdb_dbname = '{{db}}'; var couchdb_dbname = '{{db}}';
var couchdb_server = '{{couchdb_server}}' + couchdb_dbname; var couchdb_server = '{{couchdb_server}}' + couchdb_dbname;
var odoo_server = '{{odoo_server}}';
</script> </script>
<script src="{% static "js/all_common.js" %}?v="></script> <script src="{% static "js/all_common.js" %}?v="></script>
<script type="text/javascript" src="{% static 'js/orders_helper.js' %}?v="></script> <script type="text/javascript" src="{% static 'js/orders_helper.js' %}?v="></script>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment