Updating entities in bidirectional relationships causes circular error - jackson

I have a bidirectional OneToMany relationship between the entites Basket and ProductOrder.
#OneToMany(mappedBy = "basket", cascade = CascadeType.ALL)
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<ProductOrder> products = new HashSet<>();
and
#ManyToOne
#JsonIgnoreProperties("products")
private Basket basket;
When I add a new productOrder to the basket and call the update method on the basket. The productOrder is being created but gets no reference to the basket which results in the basket having no productOrders!
I tried setting the basket from the productOrder but then it ends in a endless circle and I get:
ERROR TypeError: Converting circular structure to JSON
So my question is, how to handle bidirectional relationships in jhipster?
This is how I would like to update my basket:
test-component.ts
intoBasket(product, amount) {
this.productOrder = new ProductOrder();
this.productOrder.product = product;
this.productOrder.amount = amount;
this.basketService.find(+this.account.id).subscribe((res: HttpResponse<Basket>) => {
this.basket = res.body;
this.productOrder.basket = this.basket;
this.basket.products.push(this.productOrder);
this.basketService.update(this.basket).subscribe((res: HttpResponse<Basket>) => {
console.log("test");
});
});
}
thank you!
Update
I moved some logic from the frontend to the backend:
BasketService.java
public Basket save(Basket basket) {
log.debug("Request to save Basket : {}", basket);
log.info(basket.getProducts().toString());
basket.getProducts().stream().forEach(p -> p.setBasket(basket));
return basketRepository.save(basket);
}
this saves the ProductOrders properly with a reference to the Basket. But When I try to log the products from the basket in the frontend I get null which is odd because the method
this.basketService.update(this.basket).subscribe((res: HttpResponse<Basket>) => {
console.log(res.body.products);
});
actually returns the basket filled with the new product. But it doesn't seem to save it because when I request that specific basket "/baskets/39" the response is missing the products:
{id: 39, totalPrice: 0, customerId: 39, products: null}
Update 2
okay, i restarted the product microservice which is responsible for these entities and now everything works fine. I didn't know I had to restart it but that's good to know I guess.

Related

getProduct()->getTag() return null, when it should return tags associated to the Product

In my project, we have products that has tag called serviceItem. Those item with that tag when ordered should be separated by the quantity into individuals order.
It issue is that getTags() returns null, and getTagIds gets "Call to a member function getTagIds() on null" when it gets to the next loop.
Is there a reason for why getTags() returns null?
private function transformOrderLines(OrderEntity $order): array
{
/**
* TODO: If we need to send advanced prices,
* the price value of the the lines array should be changed to caldulate the advanced price,
* with the built in quantity calculator
*/
$lines = [];
foreach ($order->getLineItems() as $orderLine) {
$hasDsmServiceItemTag = $orderLine->getProduct()->getTags();
$lines[] = [
'name' => $orderLine->getLabel(),
'sku' => substr($orderLine->getProduct()->getProductNumber(), 0, 19),
'price' => (string) ($orderLine->getProduct()->getPrice()->first()->getNet()
* $order->getCurrencyFactor()), //gets original price, calculates factor
'quantity' => (string) $orderLine->getQuantity()
];
}
$shipping = $this->transformShipping($order);
if ($shipping) {
$lines = array_merge($lines, $shipping);
}
return $lines;
}`
I also tried $orderLine->getProduct()->getTags()->getName() it also return "Call to a member function getTags() on null"
The problem is wherever the $order is fetched from the DB the orderLineItem.product.tag association is not included in the criteria.
For performance reasons shopware does not lazily load all association when you access them on entities, but you have to exactly define which associations should be included when you fetch the entities from the database.
For the full explanation take a look at the docs.

Laravel 8 left join where clause is ambiguous

I'm trying to use leftJoin but I'm having problem with conflicts between equal names in both tables.
Tables
products: added_by - user_id - published - approved - featured
product_types: added_by - user_id - published - approved - featured
$products = ProductType::
leftJoin('products', 'products.product_type_id', '=', 'product_types.id')
->select('product_types.*')
How to solve this problem?
You should start by implementing the correct relationships, it will help you in the future.
class ProductType extends Model {
public function products(): HasMany
{
return $this->hasMany(Product::class);
}
// Add the other missing relations too (user, etc)
}
class Product extends Model {
public function productType(): BelongsTo
{
return $this->belongsTo(ProductType::class);
}
// Add the other missing relations too (user, etc)
}
You can now use:
// Query all Product Types with related products
$productTypes = ProductType::with('products')->get();
// Query all ProductTypes that have products
$productTypes = ProductType::withWhereHas('products')->get();
/** #var ProductType $productType */
foreach ($productTypes as $productType) {
// You have access to the collection of associated products, in memory
$productType->products;
}
More information on eloquent relationships in https://laravel.com/docs/9.x/eloquent-relationships

.Net Core 5 Create Order and OrderDetail

I am creating Order including OrderDetail. When I have a Cart consisting of many Products, I create an Order, I want each product ID to be added to the OrderDetail including the OrderID.
But currently, I only get a ProductID (OrderID) in the first loop added to the OrderDetail. When I debug, the loop still executes enough times quantity of Product in Cart but is not added to OrderDetail.
So what is the problem that I am facing here?
Repository
public bool CreateOrder(CartViewModel invoiceVM, string userId)
{
invoiceVM.Invoices.CreateAt = DateTime.Now;
_dbContext.Invoice.Add(invoiceVM.Invoices);
_dbContext.SaveChanges();
decimal orderTotal = 0;
var cartItems = GetCartItem(userId);
foreach (var item in cartItems)
{
var invoiceDetail = new InvoiceDetails
{
ProductId = item.Products.Id,
InvoiceId = invoiceVM.Invoices.Id,
Price = item.Products.Price * item.Quantity,
Quantity = item.Quantity,
};
orderTotal += (item.Quantity * item.Products.Price);
_dbContext.InvoiceDetails.Add(invoiceDetail);
}
invoiceVM.Invoices.OrderTotal = orderTotal;
_dbContext.SaveChanges();
return true;
}
"but is not added to OrderDetail" You mean that the Order is created in your database, But you can't see any OrderDetail in your database ?
if
_dbContext.InvoiceDetails.Add(invoiceDetail);
.
.
_dbContext.SaveChanges();
are successfully pass with no errors, It save data in your database and I think it's your CartViewModel that is not updating.
you can add your data to CartViewModel in you loop or run another GetInvoice() from your dbContext.

PayPal Api Patch on Itemlist doesn't work

I want to add an item to my transaction.
$json = '
[
{
"name": "Voucher",
"description":"Voucher",
"price":"50.00",
"currency":"EUR",
"quantity":"1"
}
]';
$patchAddItem = new \PayPal\Api\Patch();
$patchAddItem->setOp('add')
->setPath('/transactions/0/item_list/items')
->setValue(json_decode($json));
$patchReplace = new \PayPal\Api\Patch();
$patchReplace->setOp('replace')
->setPath('/transactions/0/amount')
->setValue(json_decode('{
"total": "159.00",
"currency": "EUR",
}'));
$patchRequest = new \PayPal\Api\PatchRequest();
$patchRequest->setPatches(array($patchAddItem, $patchReplace));
try {
$this->payment->update($patchRequest, $this->apiContext);
} catch (PayPal\Exception\PayPalConnectionExceptio $ex) {
echo '<pre>';print_r(json_decode($ex->getData()));exit;
}
But I get following Error
Eception: Got Http response code 400 when accessing https://api.sandbox.paypal.com/v1/payments/payment/PAY... in PayPal-PHP-SDK/paypal/rest-api-sdk-php/lib/PayPal/Core/PayPalHttpConnection.php on line 154
PayPal-PHP-SDK/paypal/rest-api-sdk-php/lib/PayPal/Transport/PayPalRestCall.php on line 73: PayPal\Core\PayPalHttpConnection->execute("[{"op":"add","path":"/transactions/0/item_list/ite"... )
PayPal-PHP-SDK/paypal/rest-api-sdk-php/lib/PayPal/Common/PayPalResourceModel.php on line 102: PayPal\Transport\PayPalRestCall->execute(array[1],"/v1/payments/payment/PAY-1S151200BX2478240LEAG3CI","PATCH","[{"op":"add","path":"/transactions/0/item_list/ite"... ,null)
PayPal-PHP-SDK/paypal/rest-api-sdk-php/lib/PayPal/Api/Payment.php on line 615: PayPal\Common\PayPalResourceModel::executeCall("/v1/payments/payment/PAY-1S151200BX2478240LEAG3CI","PATCH","[{"op":"add","path":"/transactions/0/item_list/ite"... ,null,object,null)
At this moment I didn't execute the payment object. Do I have to edit the total attribut from amount too? Well, I tried this too, with same issue...
Even if you are sending only one item to PayPal you still have to set them as an item list with setItemList().
That array should be visible if you json_decode in your payment array:
[item_list] => Array
(
[items] => Array
(
[0] => Array
(
[name] => Ground Coffee 40 oz
[sku] => 123123
[price] => 52.80
[currency] => USD
[quantity] => 1
)
)
I had not run a patch for an item yet. I attempted to send an 'add' similar to your code and tried changing the path to '/transactions/0/item_list/items/1' using the next number in the items array. But could not get an add to work.
The only way I could modify the item_list was to do a complete 'replace' of the item_list, so in a running shopping cart would have to include all the items being purchased, not just the new item.
To do this I prefer to use the functions from the PayPal sdk vs building the json arrays. Their examples of how to create and execute a payment are fairly good and use the SDK functions. http://paypal.github.io/PayPal-PHP-SDK/sample/
However the example on updating a payments builds the json arrays outright.
Below is a testing function to modify the item_list using the Paypay PHP SDK Class Functions. I hard coded the Subtotal and Total to match the values coming form the shopping cart plus the increase from the new item. The item_list is also hard coded using PP's example data. Otherwise item's arrays would be built off of a user's shopping cart items. The type is set to 'replace'.
So, yes. Subtotals and Totals need to be updated to match as well, else the PP call will fail.
function updatePayPalPayment ($type, $createdPayment, $total, $subtotal, $shipping, $currency) {
$subtotal = '54.80';
$total = '71.73';
$details = new Details();
$details->setShipping($shipping)
->setSubtotal($subtotal);
$amount = new Amount();
$amount->setCurrency($currency)
->setTotal($total)
->setDetails($details);
$item1 = new Item();
$item1->setName('Ground Coffee 40 oz')
->setCurrency('USD')
->setQuantity(1)
->setSku("123123") // Similar to `item_number` in Classic API
->setPrice(52.80);
$item2 = new Item();
$item2->setName('Granola bars')
->setCurrency('USD')
->setQuantity(1)
->setSku("321321") // Similar to `item_number` in Classic API
->setPrice(2.0);
$itemList = new ItemList();
$itemList->setItems(array($item1, $item2));
$patchItem = new Patch();
$patchItem->setOp($type)
->setPath('/transactions/0/item_list')
->setValue($itemList);
$patchAmount = new Patch();
$patchAmount->setOp($type)
->setPath('/transactions/0/amount')
->setValue($amount);
$patchRequest = new PatchRequest();
$patchRequest->setPatches(array($patchAmount, $patchItem));
$update = $createdPayment->update($patchRequest, getApiContext());
return $update;
}
I also have found it very helpful to set the apiContext for logging to DEBUG and output to a file in development for much better error messages.
'log.LogEnabled' => true,
'log.FileName' => '_PayPal.log',
'log.LogLevel' => 'DEBUG',
Hope that helps.

Can't update product in magento module

have an issue updating magento product from frontend using a module that its function is for customers to create their own products and have the admin approve before enabled(this part is working).
the problem is when a customer tries to updated their admin approved product (as before approval, product states that newly created product is pending, but they can still update the data/attributes created during the product create function, the same attributes that are not updating using the controller)
first of all i have a controller with the action to update the approved/pending customer product
public function editPostAction() {
$id = $this->getRequest()->getParam('productid');
if ( $id !== false ) {
list($data, $errors) = $this->validatePost();
if ( !empty($errors) ) {
foreach ($errors as $message) {
$this->_getSession()->addError($message);
}
$this->_redirect('customer/products/edit/', array(
'id' => $id
));
} else {
$customerId = $this->_getSession()->getCustomer()->getid();
$product = Mage::getResourceModel('customerpartner/customerpartner_product_collection')
->addAttributeToSelect('*')
->addAttributeToFilter('customer_id', $customerId)
->addAttributeToFilter('entity_id', $id)
->load()
->getFirstItem();
$product->setName($this->getRequest()->getParam('name'));
$product->setSku($this->getRequest()->getParam('sku'));
$product->setDescription($this->getRequest()->getParam('description'));
$product->setShortDescription($this->getRequest()->getParam('short_description'));
$product->setPrice($this->getRequest()->getParam('price'));
$product->setWeight($this->getRequest()->getParam('weight'));
$product->setStock($this->getRequest()->getParam('stock'));
$product->save();
if ( isset($_FILES) && count($_FILES) > 0 ) {
foreach($_FILES as $image ) {
if ( $image['tmp_name'] != '' ) {
if ( ( $error = $this->uploadImage($image, $id) ) !== true ) {
$errors[] = $error;
}
}
}
}
if ( empty($errors) ) {
$this->_getSession()->addSuccess($this->__('Your product was successfully updated'));
} else {
$this->_getSession()->addError('Product info was saved but was imposible to save the image');
foreach ($errors as $message) {
$this->_getSession()->addError($message);
}
}
$this->_redirect('customer/products/');
}
}
}
as well as a form that on submit is supposed to update the product attributes and images but the page reloads on submit and shows successful saved message but the attributes are not updated and going back to the edit form (for each product created) for that product the values in the update form have the values of the update we just submitted, bet yet the products attributes are not updated in the catalog either (they remain the same values as entered in the create new process)
don't no if to continue to figure out what is going wrong or just move to either use api or direct sql to get the job done.
see this post Magento 1.7: Non-system product attribute not saving in PHP script the problem maybe different but the solution can be found in that post
updated to a new action to call in .phtml see below as it seems to be updating the product data as needed, still wanting to improve..
called in form using /frontendname/editApprovedPost/
public function editApprovedPostAction() {
$id = $this->getRequest()->getParam('productid');
$idproduct = $this->getRequest()->getParam('product_id');
if ( $id !== false ) {
list($data, $errors) = $this->validatePost();
if ( !empty($errors) ) {
foreach ($errors as $message) {
$this->_getSession()->addError($message);
}
$this->_redirect('customer/products/edit/', array(
'id' => $id
));
} else {
- now added more php code to action (in this order) after the } else {...
require_once 'app/Mage.php';
then add admin store for frontend product updates...
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
then get the customer id...
$customerId = Mage::getSingleton('customer/session')->getCustomerId();
then use the forms product Id to get the Product Id to update...
$product = Mage::getModel('catalog/product')->load("".$idproduct."");
then use setName() to update/save the attribute value grabbed from the forms input value...
$product->setName($this->getRequest()->getParam('name'));//use whatever attributes need (only text and text area tested so far)
then save/update product data with...
$product->save();
then add to run through errors...
if ( empty($errors) ) {
$this->_getSession()->addSuccess($this->__('Your product was successfully updated'));
} else {
$this->_getSession()->addError('Product info was saved but was imposible to save the image');
foreach ($errors as $message) {
$this->_getSession()->addError($message);
}
}
$this->_redirect('customer/products/');
}
}
}
then with a form to submit in frontend with customer logged in and customer group config
custom form only visible to Customer Group 2 (default is Wholesale)
form below....
sorry cant paste form to much work to paste the code here, any way using the
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
which i have read in some posts is that to update product in frontend you need to be "admin", which this seems to do just fine. As Noted before, the script was not updating and it was because it is trying to save to a different models data when the data to be updated was an actual product (that has been approved and created using the different models data) and it was updating using
$product = Mage::getResourceModel('customerpartner/customerpartner_product_collection')
would be good to here anyone else's comments
hope this helps someone because was think time to close this build.