Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MARP-1448 Create marketplace hotfix 1.5.1 #237

Merged
merged 7 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions marketplace-migration/marketplace_script_1.5.1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
function moveProductFieldsAndCleanUp() {
const products = db.getCollection("Product").find({}, {
_id: 1,
installationCount: 1,
synchronizedInstallationCount: 1,
customOrder: 1
}).toArray();

if (products.length > 0) {
db.getCollection("ProductMarketplaceData").insertMany(products);
print("Fields successfully moved to ProductMarketplaceData.");
} else {
print("No fields to move.");
}

const result = db.getCollection("Product").updateMany(
{},
{ $unset: { installationCount: "", synchronizedInstallationCount: "", customOrder: "" } }
);
print(`Fields removed from ${result.modifiedCount} documents in the Product collection.`);
}

moveProductFieldsAndCleanUp();
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ public class EntityConstants {
public static final String IMAGE = "Image";
public static final String MAVEN_ARTIFACT_VERSION = "MavenArtifactVersion";
public static final String EXTERNAL_DOCUMENT_META = "ExternalDocumentMeta";
public static final String PRODUCT_MARKETPLACE_DATA = "ProductMarketplaceData";
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
public class MongoDBConstants {
public static final String ID = "_id";
public static final String PRODUCT_COLLECTION = "Product";
public static final String PRODUCT_MARKETPLACE_COLLECTION = "ProductMarketplaceData";
public static final String MARKETPLACE_DATA = "marketplaceData";
public static final String MARKETPLACE_DATA_CUSTOM_ORDER = "marketplaceData.customOrder";
public static final String INSTALLATION_COUNT = "InstallationCount";
public static final String SYNCHRONIZED_INSTALLATION_COUNT = "SynchronizedInstallationCount";
public static final String PRODUCT_ID = "productId";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ public class RequestMappingConstants {
public static final String VERSIONS_BY_ID = "/{id}/versions";
public static final String PRODUCT_BY_ID = "/product/{id}";
public static final String PRODUCT_RATING_BY_ID = "/product/{id}/rating";
public static final String INSTALLATION_COUNT_BY_ID = "/installationcount/{id}";
public static final String INSTALLATION_COUNT_BY_ID = "/installation-count/{id}";
public static final String PRODUCT_JSON_CONTENT_BY_PRODUCT_ID_AND_VERSION = "/{id}/{version}/json";
public static final String VERSIONS_IN_DESIGNER = "/{id}/designerversions";
public static final String DESIGNER_INSTALLATION_BY_ID = "/installation/{id}/designer";
public static final String CUSTOM_SORT = "custom-sort";
public static final String LATEST_ARTIFACT_DOWNLOAD_URL_BY_ID = "/{id}/artifact";
public static final String EXTERNAL_DOCUMENT = API + "/externaldocument";
public static final String PRODUCT_MARKETPLACE_DATA = API + "/product-marketplace-data";
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import com.axonivy.market.github.service.GHAxonIvyMarketRepoService;
import com.axonivy.market.github.service.GitHubService;
import com.axonivy.market.model.Message;
import com.axonivy.market.model.ProductCustomSortRequest;
import com.axonivy.market.model.ProductModel;
import com.axonivy.market.service.MetadataService;
import com.axonivy.market.service.ProductService;
Expand All @@ -17,7 +16,6 @@
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
Expand All @@ -33,9 +31,7 @@
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
Expand Down Expand Up @@ -177,20 +173,6 @@ public ResponseEntity<Message> syncOneProduct(
return new ResponseEntity<>(message, HttpStatus.OK);
}

@PostMapping(CUSTOM_SORT)
@Operation(hidden = true)
public ResponseEntity<Message> createCustomSortProducts(
@RequestHeader(value = AUTHORIZATION) String authorizationHeader,
@RequestBody @Valid ProductCustomSortRequest productCustomSortRequest) {
String token = AuthorizationUtils.getBearerToken(authorizationHeader);
gitHubService.validateUserInOrganizationAndTeam(token, GitHubConstants.AXONIVY_MARKET_ORGANIZATION_NAME,
GitHubConstants.AXONIVY_MARKET_TEAM_NAME);
productService.addCustomSortProduct(productCustomSortRequest);
var message = new Message(ErrorCode.SUCCESSFUL.getCode(), ErrorCode.SUCCESSFUL.getHelpText(),
"Custom product sort order added successfully");
return new ResponseEntity<>(message, HttpStatus.OK);
}

@SuppressWarnings("unchecked")
private ResponseEntity<PagedModel<ProductModel>> generateEmptyPagedModel() {
var emptyPagedModel = (PagedModel<ProductModel>) pagedResourcesAssembler.toEmptyModel(Page.empty(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
Expand Down Expand Up @@ -73,18 +72,6 @@ public ResponseEntity<ProductDetailModel> findBestMatchProductDetailsByVersion(
HttpStatus.OK);
}

@PutMapping(INSTALLATION_COUNT_BY_ID)
@Operation(summary = "Update installation count of product",
description = "By default, increase installation count when click download product files by users")
public ResponseEntity<Integer> syncInstallationCount(
@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "approval-decision-utils",
in = ParameterIn.PATH) String productId,
@RequestParam(name = DESIGNER_VERSION, required = false) @Parameter(in = ParameterIn.QUERY,
example = "v10.0.20") String designerVersion) {
int result = productService.updateInstallationCountForProduct(productId, designerVersion);
return new ResponseEntity<>(result, HttpStatus.OK);
}

@GetMapping(BY_ID)
@Operation(summary = "get product detail by ID", description = "Return product detail by product id (from meta.json)")
public ResponseEntity<ProductDetailModel> findProductDetails(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.axonivy.market.controller;

import com.axonivy.market.constants.GitHubConstants;
import com.axonivy.market.enums.ErrorCode;
import com.axonivy.market.github.service.GitHubService;
import com.axonivy.market.model.Message;
import com.axonivy.market.model.ProductCustomSortRequest;
import com.axonivy.market.service.ProductMarketplaceDataService;
import com.axonivy.market.util.AuthorizationUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import static com.axonivy.market.constants.RequestMappingConstants.*;
import static com.axonivy.market.constants.RequestParamConstants.DESIGNER_VERSION;
import static com.axonivy.market.constants.RequestParamConstants.ID;
import static org.springframework.http.HttpHeaders.AUTHORIZATION;

@RestController
@RequestMapping(PRODUCT_MARKETPLACE_DATA)
@Tag(name = "Product Marketplace Data Controller", description = "API collection to get product marketplace data")
@AllArgsConstructor
public class ProductMarketplaceDataController {
private final GitHubService gitHubService;
private final ProductMarketplaceDataService productMarketplaceDataService;

@PostMapping(CUSTOM_SORT)
@Operation(hidden = true)
public ResponseEntity<Message> createCustomSortProducts(
@RequestHeader(value = AUTHORIZATION) String authorizationHeader,
@RequestBody @Valid ProductCustomSortRequest productCustomSortRequest) {
String token = AuthorizationUtils.getBearerToken(authorizationHeader);
gitHubService.validateUserInOrganizationAndTeam(token, GitHubConstants.AXONIVY_MARKET_ORGANIZATION_NAME,
GitHubConstants.AXONIVY_MARKET_TEAM_NAME);
productMarketplaceDataService.addCustomSortProduct(productCustomSortRequest);
var message = new Message(ErrorCode.SUCCESSFUL.getCode(), ErrorCode.SUCCESSFUL.getHelpText(),
"Custom product sort order added successfully");
return new ResponseEntity<>(message, HttpStatus.OK);
}

@PutMapping(INSTALLATION_COUNT_BY_ID)
@Operation(summary = "Update installation count of product",
description = "By default, increase installation count when click download product files by users")
public ResponseEntity<Integer> syncInstallationCount(
@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "approval-decision-utils",
in = ParameterIn.PATH) String productId,
@RequestParam(name = DESIGNER_VERSION, required = false) @Parameter(in = ParameterIn.QUERY,
example = "v10.0.20") String designerVersion) {
int result = productMarketplaceDataService.updateInstallationCountForProduct(productId, designerVersion);
return new ResponseEntity<>(result, HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,22 @@ public class Product implements Serializable {
private String compatibility;
private Boolean validate;
private Boolean contactUs;
@Transient
private int installationCount;
private Date newestPublishedDate;
private String newestReleaseVersion;
@Transient
private ProductModuleContent productModuleContent;
private List<Artifact> artifacts;
/**
* @deprecated
*/
@Deprecated(forRemoval = true, since = "1.6.0")
private Boolean synchronizedInstallationCount;
/**
* @deprecated
*/
@Deprecated(forRemoval = true, since = "1.6.0")
private Integer customOrder;
private List<String> releasedVersions;
@Transient
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.axonivy.market.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import java.io.Serial;
import java.io.Serializable;

import static com.axonivy.market.constants.EntityConstants.PRODUCT_MARKETPLACE_DATA;

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Document(PRODUCT_MARKETPLACE_DATA)
public class ProductMarketplaceData implements Serializable {
@Serial
private static final long serialVersionUID = -8770801879877277456L;
@Id
private String id;
private int installationCount;
private Boolean synchronizedInstallationCount;
private Integer customOrder;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
@Getter
@AllArgsConstructor
public enum SortOption {
POPULARITY("popularity", "installationCount", Sort.Direction.DESC),
POPULARITY("popularity", "marketplaceData.installationCount", Sort.Direction.DESC),
ALPHABETICALLY("alphabetically", "names", Sort.Direction.ASC),
RECENT("recent", "newestPublishedDate", Sort.Direction.DESC),
STANDARD("standard", "customOrder", Sort.Direction.DESC),
STANDARD("standard", "marketplaceData.customOrder", Sort.Direction.DESC),
ID("id", "_id", Sort.Direction.ASC);

private final String option;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,6 @@ public static Product mappingByMetaJSONFile(Product product, GHContent ghContent

public static void transferComputedPersistedDataToProduct(Product persisted, Product product) {
product.setMarketDirectory(persisted.getMarketDirectory());
product.setCustomOrder(persisted.getCustomOrder());
product.setInstallationCount(persisted.getInstallationCount());
product.setSynchronizedInstallationCount(persisted.getSynchronizedInstallationCount());
}

private static Map<String, String> mappingMultilingualismValueByMetaJSONFile(List<DisplayValue> list) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.axonivy.market.repository;

public interface CustomProductMarketplaceDataRepository {

int updateInitialCount(String productId, int initialCount);

int increaseInstallationCount(String productId);

void increaseInstallationCountForProductByDesignerVersion(String productId, String designerVersion);

void checkAndInitProductMarketplaceDataIfNotExist(String productId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,10 @@
public interface CustomProductRepository {
Product getProductByIdAndVersion(String id, String version);

Product getProductWithModuleContent(String id);

Product findProductById(String id);

List<String> getReleasedVersionsById(String id);

int updateInitialCount(String productId, int initialCount);

int increaseInstallationCount(String productId);

void increaseInstallationCountForProductByDesignerVersion(String productId, String designerVersion);

List<Product> getAllProductsWithIdAndReleaseTagAndArtifact();

Page<Product> searchByCriteria(ProductSearchCriteria criteria, Pageable pageable);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.axonivy.market.repository;

import com.axonivy.market.entity.ProductMarketplaceData;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ProductMarketplaceDataRepository extends MongoRepository<ProductMarketplaceData, String>, CustomProductMarketplaceDataRepository {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.axonivy.market.repository.impl;

import com.axonivy.market.constants.MongoDBConstants;
import com.axonivy.market.entity.ProductDesignerInstallation;
import com.axonivy.market.entity.ProductMarketplaceData;
import com.axonivy.market.repository.CustomProductMarketplaceDataRepository;
import com.axonivy.market.repository.CustomRepository;
import lombok.AllArgsConstructor;
import lombok.Builder;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

@Builder
@AllArgsConstructor
public class CustomProductMarketplaceDataRepositoryImpl extends CustomRepository implements CustomProductMarketplaceDataRepository {

final MongoTemplate mongoTemplate;

@Override
public int updateInitialCount(String productId, int initialCount) {
Update update = new Update().inc(MongoDBConstants.INSTALLATION_COUNT, initialCount).set(
MongoDBConstants.SYNCHRONIZED_INSTALLATION_COUNT, true);
ProductMarketplaceData updatedProductMarketplaceData = mongoTemplate.findAndModify(createQueryById(productId),
update, FindAndModifyOptions.options().returnNew(true), ProductMarketplaceData.class);
return updatedProductMarketplaceData != null ? updatedProductMarketplaceData.getInstallationCount() : 0;
}

@Override
public int increaseInstallationCount(String productId) {
Update update = new Update().inc(MongoDBConstants.INSTALLATION_COUNT, 1);
ProductMarketplaceData updatedProduct = mongoTemplate.findAndModify(createQueryById(productId), update,
FindAndModifyOptions.options().returnNew(true), ProductMarketplaceData.class);
return updatedProduct != null ? updatedProduct.getInstallationCount() : 0;
}

@Override
public void increaseInstallationCountForProductByDesignerVersion(String productId, String designerVersion) {
Update update = new Update().inc(MongoDBConstants.INSTALLATION_COUNT, 1);
mongoTemplate.upsert(createQueryByProductIdAndDesignerVersion(productId, designerVersion),
update, ProductDesignerInstallation.class);
}

@Override
public void checkAndInitProductMarketplaceDataIfNotExist(String productId) {
Query query = new Query(Criteria.where(MongoDBConstants.ID).is(productId));
if (!mongoTemplate.exists(query, ProductMarketplaceData.class)) {
ProductMarketplaceData productMarketplaceData = new ProductMarketplaceData();
productMarketplaceData.setId(productId);
mongoTemplate.insert(productMarketplaceData);
}
}

private Query createQueryByProductIdAndDesignerVersion(String productId, String designerVersion) {
return new Query(Criteria.where(MongoDBConstants.PRODUCT_ID).is(productId)
.andOperator(Criteria.where(MongoDBConstants.DESIGNER_VERSION).is(designerVersion)));
}
}
Loading
Loading