extern "C" PyObject* OperationItemSupplier::createOrder( PyObject *self, PyObject *args, PyObject *kwdict ) { // Parse the Python arguments PyObject* pylocation = NULL; unsigned long id = 0; const char* ref = NULL; PyObject* pyitem = NULL; PyObject* pysupplier = NULL; double qty = 0; PyObject* pystart = NULL; PyObject* pyend = NULL; const char* status = NULL; const char* source = NULL; static const char *kwlist[] = { "location", "id", "reference", "item", "supplier", "quantity", "start", "end", "status", "source", NULL }; int ok = PyArg_ParseTupleAndKeywords( args, kwdict, "|OkzOOdOOzz:createOrder", const_cast<char**>(kwlist), &pylocation, &id, &ref, &pyitem, &pysupplier, &qty, &pystart, &pyend, &status, &source ); if (!ok) return NULL; Date start = pystart ? PythonData(pystart).getDate() : Date::infinitePast; Date end = pyend ? PythonData(pyend).getDate() : Date::infinitePast; // Validate all arguments if (!pylocation || !pyitem) { PyErr_SetString(PythonDataException, "item and location arguments are mandatory"); return NULL; } PythonData location_tmp(pylocation); if (!location_tmp.check(Location::metadata)) { PyErr_SetString(PythonDataException, "location argument must be of type location"); return NULL; } PythonData item_tmp(pyitem); if (!item_tmp.check(Item::metadata)) { PyErr_SetString(PythonDataException, "item argument must be of type item"); return NULL; } PythonData supplier_tmp(pysupplier); if (pysupplier && !supplier_tmp.check(Supplier::metadata)) { PyErr_SetString(PythonDataException, "supplier argument must be of type supplier"); return NULL; } Item *item = static_cast<Item*>(item_tmp.getObject()); Location *location = static_cast<Location*>(location_tmp.getObject()); Supplier *supplier = pysupplier ? static_cast<Supplier*>(supplier_tmp.getObject()) : NULL; // Find or create the destination buffer. Buffer* destbuffer = NULL; Item::bufferIterator buf_iter(item); while (Buffer* tmpbuf = buf_iter.next()) { if (tmpbuf->getLocation() == location) { if (destbuffer) { stringstream o; o << "Multiple buffers found for item '" << item << "'' and location'" << location << "'"; throw DataException(o.str()); } destbuffer = tmpbuf; } } if (!destbuffer) { // Create the destination buffer destbuffer = new BufferDefault(); stringstream o; o << item << " @ " << location; destbuffer->setName(o.str()); destbuffer->setItem(item); destbuffer->setLocation(location); } // Build the producing operation for this buffer. destbuffer->getProducingOperation(); // Look for a matching operation replenishing this buffer. Operation *oper = NULL; for (Buffer::flowlist::const_iterator flowiter = destbuffer->getFlows().begin(); flowiter != destbuffer->getFlows().end() && !oper; ++flowiter) { if (flowiter->getOperation()->getType() != *OperationItemSupplier::metadata) continue; OperationItemSupplier* opitemsupplier = static_cast<OperationItemSupplier*>(flowiter->getOperation()); if (supplier) { if (supplier->isMemberOf(opitemsupplier->getItemSupplier()->getSupplier())) oper = opitemsupplier; } else oper = opitemsupplier; } // No matching operation is found. if (!oper) { // We'll create one now, but that requires that we have a supplier defined. if (!supplier) throw DataException("Supplier is needed on this purchase order"); // Note: We know that we need to create a new one. An existing one would // have created an operation on the buffer already. ItemSupplier *itemsupplier = new ItemSupplier(); itemsupplier->setSupplier(supplier); itemsupplier->setItem(item); itemsupplier->setLocation(location); oper = new OperationItemSupplier(itemsupplier, destbuffer); new ProblemInvalidData(oper, "Purchase orders on unauthorized supplier", "operation", Date::infinitePast, Date::infiniteFuture, 1); } // Finally, create the operationplan OperationPlan *opplan = oper->createOperationPlan(qty, start, end); if (id) opplan->setRawIdentifier(id); // We can use this fast method because we call activate later if (status) opplan->setStatus(status); // Reset quantity after the status update to assure that // also non-valid quantities are getting accepted. opplan->setQuantity(qty); if (ref) opplan->setReference(ref); opplan->activate(); // Return result Py_INCREF(opplan); return opplan; }
PyObject* ItemSupplier::create(PyTypeObject* pytype, PyObject* args, PyObject* kwds) { try { // Pick up the supplier PyObject* sup = PyDict_GetItemString(kwds,"supplier"); if (!sup) throw DataException("missing supplier on ItemSupplier"); if (!PyObject_TypeCheck(sup, Supplier::metadata->pythonClass)) throw DataException("ItemSupplier supplier must be of type supplier"); // Pick up the item PyObject* it = PyDict_GetItemString(kwds,"item"); if (!it) throw DataException("missing item on ItemSupplier"); if (!PyObject_TypeCheck(it, Item::metadata->pythonClass)) throw DataException("ItemSupplier item must be of type item"); // Pick up the priority PyObject* q1 = PyDict_GetItemString(kwds,"priority"); int q2 = q1 ? PythonData(q1).getInt() : 1; // Pick up the effective dates DateRange eff; PyObject* eff_start = PyDict_GetItemString(kwds,"effective_start"); if (eff_start) { PythonData d(eff_start); eff.setStart(d.getDate()); } PyObject* eff_end = PyDict_GetItemString(kwds,"effective_end"); if (eff_end) { PythonData d(eff_end); eff.setEnd(d.getDate()); } // Create the ItemSupplier ItemSupplier *l = new ItemSupplier( static_cast<Supplier*>(sup), static_cast<Item*>(it), q2, eff ); // Iterate over extra keywords, and set attributes. @todo move this responsibility to the readers... if (l) { PyObject *key, *value; Py_ssize_t pos = 0; while (PyDict_Next(kwds, &pos, &key, &value)) { PythonData field(value); PyObject* key_utf8 = PyUnicode_AsUTF8String(key); DataKeyword attr(PyBytes_AsString(key_utf8)); Py_DECREF(key_utf8); if (!attr.isA(Tags::effective_end) && !attr.isA(Tags::effective_start) && !attr.isA(Tags::supplier) && !attr.isA(Tags::item) && !attr.isA(Tags::type) && !attr.isA(Tags::priority) && !attr.isA(Tags::action)) { const MetaFieldBase* fmeta = l->getType().findField(attr.getHash()); if (!fmeta && l->getType().category) fmeta = l->getType().category->findField(attr.getHash()); if (fmeta) // Update the attribute fmeta->setField(l, field); else l->setProperty(attr.getName(), value); } }; } // Return the object Py_INCREF(l); return static_cast<PyObject*>(l); } catch (...) { PythonType::evalException(); return nullptr; } }
extern "C" PyObject* OperationItemSupplier::createOrder( PyObject *self, PyObject *args, PyObject *kwdict ) { // Parse the Python arguments PyObject* pylocation = NULL; unsigned long id = 0; const char* ref = NULL; PyObject* pyitem = NULL; PyObject* pysupplier = NULL; double qty = 0; PyObject* pystart = NULL; PyObject* pyend = NULL; const char* status = NULL; const char* source = NULL; static const char *kwlist[] = { "location", "id", "reference", "item", "supplier", "quantity", "start", "end", "status", "source", NULL }; int ok = PyArg_ParseTupleAndKeywords( args, kwdict, "|OkzOOdOOzz:createOrder", const_cast<char**>(kwlist), &pylocation, &id, &ref, &pyitem, &pysupplier, &qty, &pystart, &pyend, &status, &source ); if (!ok) return NULL; Date start = pystart ? PythonData(pystart).getDate() : Date::infinitePast; Date end = pyend ? PythonData(pyend).getDate() : Date::infinitePast; // Validate all arguments if (!pylocation || !pyitem) { PyErr_SetString(PythonDataException, "item and location arguments are mandatory"); return NULL; } PythonData location_tmp(pylocation); if (!location_tmp.check(Location::metadata)) { PyErr_SetString(PythonDataException, "location argument must be of type location"); return NULL; } PythonData item_tmp(pyitem); if (!item_tmp.check(Item::metadata)) { PyErr_SetString(PythonDataException, "item argument must be of type item"); return NULL; } PythonData supplier_tmp(pysupplier); if (pysupplier && !supplier_tmp.check(Supplier::metadata)) { PyErr_SetString(PythonDataException, "supplier argument must be of type supplier"); return NULL; } Item *item = static_cast<Item*>(item_tmp.getObject()); Location *location = static_cast<Location*>(location_tmp.getObject()); Supplier *supplier = pysupplier ? static_cast<Supplier*>(supplier_tmp.getObject()) : NULL; // Find or create the destination buffer. Buffer* destbuffer = NULL; for (Buffer::iterator bufiter = Buffer::begin(); bufiter != Buffer::end(); ++bufiter) { if (bufiter->getLocation() == location && bufiter->getItem() == item) { if (destbuffer) { stringstream o; o << "Multiple buffers found for item '" << item << "'' and location'" << location << "'"; throw DataException(o.str()); } destbuffer = &*bufiter; } } if (!destbuffer) { // Create the destination buffer destbuffer = new BufferDefault(); stringstream o; o << item << " @ " << location; destbuffer->setName(o.str()); destbuffer->setItem(item); destbuffer->setLocation(location); } // Look for a matching matching supplying operation on this buffer. // Here we also trigger the creation of its producing operation, which // contains the logic to build possible transfer operations. Operation *oper = NULL; Operation* prodOper = destbuffer->getProducingOperation(); if (prodOper && prodOper->getType() == *OperationItemSupplier::metadata) { if (supplier) { if (supplier->isMemberOf(static_cast<OperationItemSupplier*>(prodOper)->getItemSupplier()->getSupplier())) oper = prodOper; } else oper = prodOper; } else if (prodOper && prodOper->getType() == *OperationAlternate::metadata) { SubOperation::iterator soperiter = prodOper->getSubOperationIterator(); while (SubOperation *soper = soperiter.next()) { if (soper->getType() == *OperationItemSupplier::metadata) { if (supplier) { if (supplier->isMemberOf(static_cast<OperationItemSupplier*>(prodOper)->getItemSupplier()->getSupplier())) { oper = soper->getOperation(); break; } } else { oper = prodOper; break; } } } } // No matching operation is found. if (!oper) { // We'll create one now, but that requires that we have a supplier defined. if (!supplier) throw DataException("Supplier is needed on this purchase order"); // Note: We know that we need to create a new one. An existing one would // have created an operation on the buffer already. ItemSupplier *itemsupplier = new ItemSupplier(); itemsupplier->setSupplier(supplier); itemsupplier->setItem(item); itemsupplier->setLocation(location); oper = new OperationItemSupplier(itemsupplier, destbuffer); new ProblemInvalidData(oper, "Purchase orders on unauthorized supplier", "operation", Date::infinitePast, Date::infiniteFuture, 1); } // Finally, create the operationplan OperationPlan *opplan = oper->createOperationPlan(qty, start, end); if (status) opplan->setStatus(status); if (ref) opplan->setReference(ref); // Return result Py_INCREF(opplan); return opplan; }