1 56 package org.opencrx.kernel.layer.application; 57 58 import java.lang.reflect.InvocationTargetException ; 59 import java.lang.reflect.Method ; 60 import java.math.BigDecimal ; 61 import java.text.ParseException ; 62 import java.util.ArrayList ; 63 import java.util.Arrays ; 64 import java.util.Date ; 65 import java.util.HashMap ; 66 import java.util.HashSet ; 67 import java.util.Iterator ; 68 import java.util.List ; 69 import java.util.Map ; 70 71 import org.codehaus.janino.ClassBodyEvaluator; 72 import org.codehaus.janino.CompileException; 73 import org.codehaus.janino.Parser; 74 import org.codehaus.janino.Scanner; 75 import org.opencrx.kernel.generic.OpenCrxException; 76 import org.openmdx.base.accessor.jmi.cci.RefPackage_1_0; 77 import org.openmdx.base.exception.ServiceException; 78 import org.openmdx.compatibility.base.dataprovider.cci.AttributeSelectors; 79 import org.openmdx.compatibility.base.dataprovider.cci.DataproviderObject; 80 import org.openmdx.compatibility.base.dataprovider.cci.DataproviderObject_1_0; 81 import org.openmdx.compatibility.base.dataprovider.cci.Directions; 82 import org.openmdx.compatibility.base.dataprovider.cci.RequestCollection; 83 import org.openmdx.compatibility.base.dataprovider.cci.ServiceHeader; 84 import org.openmdx.compatibility.base.dataprovider.cci.SystemAttributes; 85 import org.openmdx.compatibility.base.marshalling.Marshaller; 86 import org.openmdx.compatibility.base.naming.Path; 87 import org.openmdx.compatibility.base.query.FilterOperators; 88 import org.openmdx.compatibility.base.query.FilterProperty; 89 import org.openmdx.compatibility.base.query.Quantors; 90 import org.openmdx.kernel.exception.BasicException; 91 import org.openmdx.model1.accessor.basic.cci.Model_1_0; 92 93 public class Products { 94 95 public Products( 97 Model_1_0 model, 98 OpenCrxKernel_1 plugin, 99 RequestCollection delegation, 100 RefPackage_1_0 rootPkg 101 ) { 102 this.model = model; 103 this.plugin = plugin; 104 this.delegation = delegation; 105 this.rootPkg = rootPkg; 106 } 107 108 public void cloneProductConfigurationSet( 110 ServiceHeader header, 111 Path fromIdentity, 112 Path toIdentity, 113 boolean cloneDefaultOnly, 114 boolean updateCurrentConfig 115 ) throws ServiceException { 116 List configurations = this.delegation.addFindRequest( 117 fromIdentity.getChild("configuration"), 118 null, 119 AttributeSelectors.ALL_ATTRIBUTES, 120 0, 121 Integer.MAX_VALUE, 122 Directions.ASCENDING 123 ); 124 for( 125 Iterator i = configurations.iterator(); 126 i.hasNext(); 127 ) { 128 DataproviderObject_1_0 configuration = (DataproviderObject_1_0)i.next(); 129 if( 130 !cloneDefaultOnly || 131 ((configuration.values("isDefault").size() > 0) && ((Boolean )configuration.values("isDefault").get(0)).booleanValue()) 132 ) { 133 this.plugin.cloneable.cloneAndUpdateReferences( 134 header, 135 configuration, 136 toIdentity.getChild("configuration"), 137 null, 138 "property", 139 true 140 ); 141 } 142 } 143 DataproviderObject_1_0 from = this.plugin.retrieveObjectFromLocal(header, fromIdentity); 145 DataproviderObject to = this.plugin.retrieveObjectForModification(toIdentity); 146 to.clearValues("configType").addAll( 147 from.values("configType") 148 ); 149 150 if(updateCurrentConfig) { 152 configurations = this.delegation.addFindRequest( 154 toIdentity.getChild("configuration"), 155 null, 156 AttributeSelectors.ALL_ATTRIBUTES, 157 0, 158 Integer.MAX_VALUE, 159 Directions.ASCENDING 160 ); 161 Path defaultConfigurationIdentity = null; 162 for( 163 Iterator i = configurations.iterator(); 164 i.hasNext(); 165 ) { 166 DataproviderObject_1_0 configuration = (DataproviderObject_1_0)i.next(); 167 if((configuration.values("isDefault").size() > 0) && ((Boolean )configuration.values("isDefault").get(0)).booleanValue()) { 168 defaultConfigurationIdentity = configuration.path(); 169 break; 170 } 171 } 172 if(defaultConfigurationIdentity != null) { 173 to.clearValues("currentConfig").add(defaultConfigurationIdentity); 174 } 175 } 176 } 177 178 public void setConfigurationType( 180 ServiceHeader header, 181 DataproviderObject_1_0 product, 182 Path configurationTypeIdentity 183 ) throws ServiceException { 184 this.plugin.removeAll( 185 product.path().getChild("configuration"), 186 null, 187 0, 188 new HashSet () 189 ); 190 List configurationTypes = this.delegation.addFindRequest( 191 configurationTypeIdentity.getChild("configurationType"), 192 null, 193 AttributeSelectors.ALL_ATTRIBUTES, 194 0, 195 Integer.MAX_VALUE, 196 Directions.ASCENDING 197 ); 198 Map objectMarshallers = new HashMap (); 199 objectMarshallers.put( 200 "org:opencrx:kernel:product1:ProductConfigurationType", 201 new Marshaller() { 202 public Object marshal(Object s) throws ServiceException { 203 DataproviderObject configuration = new DataproviderObject( 204 (DataproviderObject_1_0)s 205 ); 206 configuration.clearValues( 207 SystemAttributes.OBJECT_CLASS).add("org:opencrx:kernel:product1:ProductConfiguration" 208 ); 209 return configuration; 210 } 211 public Object unmarshal(Object s) { 212 throw new UnsupportedOperationException (); 213 } 214 } 215 ); 216 for( 217 Iterator i = configurationTypes.iterator(); 218 i.hasNext(); 219 ) { 220 DataproviderObject_1_0 configurationType = (DataproviderObject_1_0)i.next(); 221 DataproviderObject configuration = 222 this.plugin.cloneable.cloneAndUpdateReferences( 223 header, 224 configurationType, 225 product.path().getChild("configuration"), 226 objectMarshallers, 227 "property", 228 true 229 ); 230 configuration = this.plugin.retrieveObjectForModification(configuration.path()); 231 configuration.clearValues("configType").add( 232 configurationType.path() 233 ); 234 } 235 DataproviderObject modifiedProduct = this.plugin.retrieveObjectForModification(product.path()); 236 modifiedProduct.clearValues("configType").add( 237 configurationTypeIdentity 238 ); 239 } 240 241 public void unsetConfigurationType( 243 DataproviderObject_1_0 product 244 ) throws ServiceException { 245 246 } 247 248 public void assignProduct( 250 ServiceHeader header, 251 DataproviderObject_1_0 bundledProduct, 252 Path productIdentity 253 ) throws ServiceException { 254 DataproviderObject modifiedBundledProduct = this.plugin.retrieveObjectForModification(bundledProduct.path()); 255 modifiedBundledProduct.clearValues("product").add( 256 productIdentity 257 ); 258 DataproviderObject_1_0 product = this.plugin.retrieveObjectFromLocal( 259 header, 260 productIdentity 261 ); 262 modifiedBundledProduct.clearValues("configType").addAll( 263 product.values("configType") 264 ); 265 this.plugin.removeAll( 267 bundledProduct.path().getChild("configuration"), 268 null, 269 0, 270 new HashSet () 271 ); 272 this.cloneProductConfigurationSet( 273 header, 274 productIdentity, 275 bundledProduct.path(), 276 false, 277 true 278 ); 279 this.plugin.removeAll( 281 bundledProduct.path().getChild("depotReference"), 282 null, 283 0, 284 new HashSet () 285 ); 286 List depotReferences = this.delegation.addFindRequest( 288 productIdentity.getChild("depotReference"), 289 null, 290 AttributeSelectors.ALL_ATTRIBUTES, 291 0, 292 Integer.MAX_VALUE, 293 Directions.ASCENDING 294 ); 295 for( 296 Iterator i = depotReferences.iterator(); 297 i.hasNext(); 298 ) { 299 DataproviderObject_1_0 depotReference = (DataproviderObject_1_0)i.next(); 300 this.plugin.cloneable.cloneAndUpdateReferences( 301 header, 302 depotReference, 303 bundledProduct.path().getChild("depotReference"), 304 null, 305 "", 306 true 307 ); 308 } 309 } 310 311 public FilterProperty[] getProductFilterProperties( 313 Path productFilterIdentity 314 ) throws ServiceException { 315 List filterProperties = this.delegation.addFindRequest( 316 productFilterIdentity.getChild("productFilterProperty"), 317 null, 318 AttributeSelectors.ALL_ATTRIBUTES, 319 null, 320 0, 321 Integer.MAX_VALUE, 322 Directions.ASCENDING 323 ); 324 List filter = new ArrayList (); 325 for( 326 Iterator i = filterProperties.iterator(); 327 i.hasNext(); 328 ) { 329 DataproviderObject_1_0 filterProperty = (DataproviderObject_1_0)i.next(); 330 String filterPropertyClass = (String )filterProperty.values(SystemAttributes.OBJECT_CLASS).get(0); 331 332 Boolean isActive = (Boolean )filterProperty.values("isActive").get(0); 333 334 if((isActive != null) && isActive.booleanValue()) { 335 short filterOperator = filterProperty.values("filterOperator").size() == 0 337 ? FilterOperators.IS_IN 338 : ((Number )filterProperty.values("filterOperator").get(0)).shortValue(); 339 filterOperator = filterOperator == 0 340 ? FilterOperators.IS_IN 341 : filterOperator; 342 short filterQuantor = filterProperty.values("filterQuantor").size() == 0 343 ? Quantors.THERE_EXISTS 344 : ((Number )filterProperty.values("filterQuantor").get(0)).shortValue(); 345 filterQuantor = filterQuantor == 0 346 ? Quantors.THERE_EXISTS 347 : filterQuantor; 348 349 if("org:opencrx:kernel:product1:ProductTypeFilterProperty".equals(filterPropertyClass)) { 350 filter.add( 351 new FilterProperty( 352 filterQuantor, 353 "productType", 354 filterOperator, 355 filterProperty.values("productType").toArray() 356 ) 357 ); 358 } 359 else if("org:opencrx:kernel:product1:DefaultSalesTaxTypeFilterProperty".equals(filterPropertyClass)) { 360 filter.add( 361 new FilterProperty( 362 filterQuantor, 363 "salesTaxType", 364 filterOperator, 365 filterProperty.values("salesTaxType").toArray() 366 ) 367 ); 368 } 369 else if("org:opencrx:kernel:product1:CategoryFilterProperty".equals(filterPropertyClass)) { 370 filter.add( 371 new FilterProperty( 372 filterQuantor, 373 "category", 374 filterOperator, 375 filterProperty.values("category").toArray() 376 ) 377 ); 378 } 379 else if("org:opencrx:kernel:product1:PriceUomFilterProperty".equals(filterPropertyClass)) { 380 filter.add( 381 new FilterProperty( 382 filterQuantor, 383 "priceUom", 384 filterOperator, 385 filterProperty.values("priceUom").toArray() 386 ) 387 ); 388 } 389 } 390 } 391 return (FilterProperty[])filter.toArray(new FilterProperty[filter.size()]); 392 } 393 394 private List getAssignedPriceListEntries( 396 DataproviderObject_1_0 priceLevel 397 ) throws ServiceException { 398 List priceFilter = new ArrayList (); 399 priceFilter.add( 400 new FilterProperty( 401 Quantors.THERE_EXISTS, 402 "priceLevel", 403 FilterOperators.IS_IN, 404 new Object []{priceLevel.path()} 405 ) 406 ); 407 return this.delegation.addFindRequest( 408 priceLevel.path().getPrefix(5).getChild("priceListEntry"), 409 (FilterProperty[])priceFilter.toArray(new FilterProperty[priceFilter.size()]), 410 AttributeSelectors.ALL_ATTRIBUTES, 411 0, 412 BATCHING_MODE_SIZE, 413 Directions.ASCENDING 414 ); 415 } 416 417 private List findPrices( 419 DataproviderObject_1_0 priceLevel, 420 boolean useBasedOnPriceLevel, 421 Path productIdentity 422 ) throws ServiceException { 423 List priceFilter = new ArrayList (); 424 425 if(priceLevel.values("priceCurrency").size() > 0) { 427 priceFilter.add( 428 new FilterProperty( 429 Quantors.THERE_EXISTS, 430 "priceCurrency", 431 FilterOperators.IS_IN, 432 priceLevel.values("priceCurrency").toArray() 433 ) 434 ); 435 } 436 if(priceLevel.values("priceUsage").size() > 0) { 438 priceFilter.add( 439 new FilterProperty( 440 Quantors.THERE_EXISTS, 441 "usage", 442 FilterOperators.IS_IN, 443 priceLevel.values("priceUsage").toArray() 444 ) 445 ); 446 } 447 if(useBasedOnPriceLevel) { 449 if(priceLevel.values("basedOn").size() > 0) { 450 priceFilter.add( 451 new FilterProperty( 452 Quantors.THERE_EXISTS, 453 "priceLevel", 454 FilterOperators.IS_IN, 455 priceLevel.values("basedOn").toArray() 456 ) 457 ); 458 } 459 } 460 else { 461 priceFilter.add( 462 new FilterProperty( 463 Quantors.THERE_EXISTS, 464 "priceLevel", 465 FilterOperators.IS_IN, 466 new Object []{priceLevel.path()} 467 ) 468 ); 469 } 470 return this.delegation.addFindRequest( 471 productIdentity.getChild("basePrice"), 472 (FilterProperty[])priceFilter.toArray(new FilterProperty[priceFilter.size()]), 473 AttributeSelectors.ALL_ATTRIBUTES, 474 0, 475 BATCHING_MODE_SIZE, 476 Directions.ASCENDING 477 ); 478 } 479 480 public int movePricesFromBasedOnPriceLevel( 482 ServiceHeader header, 483 DataproviderObject_1_0 priceLevel, 484 DataproviderObject_1_0 params 485 ) throws ServiceException { 486 if( 487 ((priceLevel.values("isFinal").size() > 0) && 488 ((Boolean )priceLevel.values("isFinal").get(0)).booleanValue()) || 489 (priceLevel.values("basedOn").size() > 0) 490 ) { 491 throw new ServiceException( 492 OpenCrxException.DOMAIN, 493 OpenCrxException.PRODUCT_OPERATION_NOT_ALLOWED_FOR_NON_BASIC_PRICE_LEVEL, 494 new BasicException.Parameter[]{ 495 new BasicException.Parameter("param0", priceLevel.path()) 496 }, 497 "Operation is not allowed for final and non-basic price level." 498 ); 499 } 500 short processingMode = params.values("processingMode").size() > 0 501 ? ((Short )params.values("processingMode").get(0)).shortValue() 502 : 0; 503 504 List productFilter = new ArrayList (); 506 productFilter.addAll( 507 Arrays.asList( 508 this.getProductFilterProperties( 509 priceLevel.path() 510 ) 511 ) 512 ); 513 List filteredProducts = this.delegation.addFindRequest( 514 priceLevel.path().getPrefix(5).getChild("allProduct"), 515 (FilterProperty[])productFilter.toArray(new FilterProperty[productFilter.size()]), 516 AttributeSelectors.ALL_ATTRIBUTES, 517 0, 518 BATCHING_MODE_SIZE, 519 Directions.ASCENDING 520 ); 521 int numberProcessed = 0; 522 for( 523 Iterator i = filteredProducts.iterator(); 524 i.hasNext(); 525 ) { 526 DataproviderObject_1_0 product = (DataproviderObject_1_0)i.next(); 527 Path productIdentity = new Path((String )product.values(SystemAttributes.OBJECT_IDENTITY).get(0)); 528 List filteredPrices = this.findPrices( 529 priceLevel, 530 true, 531 productIdentity 532 ); 533 Map cachedPriceLevels = new HashMap (); 534 for( 535 Iterator j = filteredPrices.iterator(); 536 j.hasNext(); 537 ) { 538 DataproviderObject_1_0 price = (DataproviderObject_1_0)j.next(); 539 if(price.values("priceLevel").size() > 0) { 540 DataproviderObject_1_0 cachedPriceLevel = 541 (DataproviderObject_1_0)cachedPriceLevels.get(price.values("priceLevel").get(0)); 542 if(cachedPriceLevel == null) { 543 cachedPriceLevels.put( 544 price.values("priceLevel").get(0), 545 cachedPriceLevel = this.plugin.retrieveObjectFromDelegation( 546 (Path)price.values("priceLevel").get(0) 547 ) 548 ); 549 } 550 if( 551 (cachedPriceLevel.values("isFinal").size() > 0) && 552 ((Boolean )cachedPriceLevel.values("isFinal").get(0)).booleanValue() 553 ) { 554 continue; 555 } 556 } 557 if(processingMode == PROCESSING_MODE_PROCESS) { 558 DataproviderObject movedPrice = this.plugin.retrieveObjectForModification( 559 price.path() 560 ); 561 movedPrice.clearValues("priceLevel").add( 562 priceLevel.path() 563 ); 564 } 565 numberProcessed++; 566 } 567 } 568 return numberProcessed; 569 } 570 571 public int createPricesFromBasedOnPriceLevel( 573 ServiceHeader header, 574 DataproviderObject_1_0 priceLevel, 575 DataproviderObject_1_0 params 576 ) throws ServiceException { 577 if( 578 ((priceLevel.values("isFinal").size() > 0) && 579 ((Boolean )priceLevel.values("isFinal").get(0)).booleanValue()) || 580 (priceLevel.values("basedOn").size() == 0) 581 ) { 582 throw new ServiceException( 583 OpenCrxException.DOMAIN, 584 OpenCrxException.PRODUCT_OPERATION_NOT_ALLOWED_FOR_FINAL_PRICE_LEVEL, 585 new BasicException.Parameter[]{ 586 new BasicException.Parameter("param0", priceLevel.path()) 587 }, 588 "Operation is not allowed for final price level." 589 ); 590 } 591 if( 592 (priceLevel.values("basedOn").size() == 0) 593 ) { 594 throw new ServiceException( 595 OpenCrxException.DOMAIN, 596 OpenCrxException.PRODUCT_OPERATION_NOT_ALLOWED_FOR_BASIC_PRICE_LEVEL, 597 new BasicException.Parameter[]{ 598 new BasicException.Parameter("param0", priceLevel.path()) 599 }, 600 "Operation is not allowed for basic price level." 601 ); 602 } 603 List priceModifiers = this.delegation.addFindRequest( 604 priceLevel.path().getChild("priceModifier"), 605 null, 606 AttributeSelectors.ALL_ATTRIBUTES, 607 0, 608 BATCHING_MODE_SIZE, 609 Directions.ASCENDING 610 ); 611 short processingMode = params.values("processingMode").size() > 0 612 ? ((Short )params.values("processingMode").get(0)).shortValue() 613 : 0; 614 615 List productFilter = new ArrayList (); 617 productFilter.addAll( 618 Arrays.asList( 619 this.getProductFilterProperties( 620 priceLevel.path() 621 ) 622 ) 623 ); 624 List filteredProducts = this.delegation.addFindRequest( 625 priceLevel.path().getPrefix(5).getChild("allProduct"), 626 (FilterProperty[])productFilter.toArray(new FilterProperty[productFilter.size()]), 627 AttributeSelectors.ALL_ATTRIBUTES, 628 0, 629 BATCHING_MODE_SIZE, 630 Directions.ASCENDING 631 ); 632 int numberProcessed = 0; 633 for( 635 Iterator i = filteredProducts.iterator(); 636 i.hasNext(); 637 ) { 638 DataproviderObject_1_0 product = (DataproviderObject_1_0)i.next(); 639 Path productIdentity = new Path((String )product.values(SystemAttributes.OBJECT_IDENTITY).get(0)); 640 List filteredPrices = this.findPrices( 641 priceLevel, 642 true, 643 productIdentity 644 ); 645 for( 646 Iterator j = filteredPrices.iterator(); 647 j.hasNext(); 648 ) { 649 DataproviderObject_1_0 basePrice = (DataproviderObject_1_0)j.next(); 650 if(processingMode == PROCESSING_MODE_PROCESS) { 651 DataproviderObject createdPrice = new DataproviderObject( 652 basePrice.path().getParent().getChild(this.plugin.getUidAsString()) 653 ); 654 createdPrice.addClones( 655 basePrice, 656 true 657 ); 658 BigDecimal quantityFromPrice = (BigDecimal )createdPrice.values("quantityFrom").get(0); 659 BigDecimal quantityToPrice = (BigDecimal )createdPrice.values("quantityTo").get(0); 660 for( 661 Iterator k = priceModifiers.iterator(); 662 k.hasNext(); 663 ) { 664 DataproviderObject_1_0 priceModifier = (DataproviderObject_1_0)k.next(); 665 BigDecimal quantityFromModifier = (BigDecimal )priceModifier.values("quantityFrom").get(0); 666 quantityFromModifier = quantityFromModifier == null ? quantityFromPrice : quantityFromModifier; 667 BigDecimal quantityToModifier = (BigDecimal )priceModifier.values("quantityTo").get(0); 668 quantityToModifier = quantityToModifier == null ? quantityToPrice : quantityToModifier; 669 if( 671 ((quantityFromModifier == null) || (quantityFromModifier.compareTo(quantityFromPrice) <= 0)) && 672 ((quantityToModifier == null) || (quantityToModifier.compareTo(quantityToPrice) >= 0)) 673 ) { 674 String modifierType = (String )priceModifier.values(SystemAttributes.OBJECT_CLASS).get(0); 675 if("org:opencrx:kernel:product1:DiscountPriceModifier".equals(modifierType)) { 676 boolean discountIsPercentageModifier = 677 (priceModifier.values("discountIsPercentage").size() > 0) && 678 ((Boolean )priceModifier.values("discountIsPercentage").get(0)).booleanValue(); 679 boolean discountIsPercentagePrice = 680 (createdPrice.values("discountIsPercentage").size() > 0) && 681 ((Boolean )createdPrice.values("discountIsPercentage").get(0)).booleanValue(); 682 if(discountIsPercentageModifier == discountIsPercentagePrice) { 683 createdPrice.clearValues("discount").addAll( 684 priceModifier.values("discount") 685 ); 686 } 687 } 688 else if("org:opencrx:kernel:product1:LinearPriceModifier".equals(modifierType)) { 689 BigDecimal priceMultiplier = (BigDecimal )priceModifier.values("priceMultiplier").get(0); 690 priceMultiplier = priceMultiplier == null ? new BigDecimal (0) : priceMultiplier; 691 BigDecimal priceOffset = (BigDecimal )priceModifier.values("priceOffset").get(0); 692 priceOffset = priceOffset == null ? new BigDecimal (0) : priceOffset; 693 BigDecimal roundingFactor = (BigDecimal )priceModifier.values("roundingFactor").get(0); 694 roundingFactor = roundingFactor == null ? new BigDecimal (1) : roundingFactor; 695 BigDecimal price = (BigDecimal )createdPrice.values("price").get(0); 696 price = price == null ? new BigDecimal (0) : price; 697 price = 698 new BigDecimal ( 699 price.multiply(priceMultiplier).multiply(roundingFactor).add( 700 new BigDecimal (0.5) 701 ).toBigInteger() 702 ).divide( 703 roundingFactor, price.scale(), BigDecimal.ROUND_FLOOR 704 ).add( 705 priceOffset 706 ); 707 createdPrice.clearValues("price").add(price); 708 } 709 } 710 } 711 createdPrice.clearValues("priceLevel").add( 712 priceLevel.path() 713 ); 714 this.delegation.addCreateRequest( 715 createdPrice 716 ); 717 } 718 } 719 numberProcessed++; 720 } 721 return numberProcessed; 722 } 723 724 public int clearAssignedPrices( 726 ServiceHeader header, 727 DataproviderObject_1_0 priceLevel, 728 DataproviderObject_1_0 params 729 ) throws ServiceException { 730 if( 731 ((priceLevel.values("isFinal").size() > 0) && 732 ((Boolean )priceLevel.values("isFinal").get(0)).booleanValue()) 733 ) { 734 throw new ServiceException( 735 OpenCrxException.DOMAIN, 736 OpenCrxException.PRODUCT_OPERATION_NOT_ALLOWED_FOR_FINAL_PRICE_LEVEL, 737 new BasicException.Parameter[]{ 738 new BasicException.Parameter("param0", priceLevel.path()) 739 }, 740 "Operation is not allowed for final price level." 741 ); 742 } 743 if(this.isBasedOnPriceLevel(priceLevel.path())) { 744 throw new ServiceException( 745 OpenCrxException.DOMAIN, 746 OpenCrxException.PRODUCT_OPERATION_NOT_ALLOWED_FOR_FINAL_PRICE_LEVEL, 747 new BasicException.Parameter[]{ 748 new BasicException.Parameter("param0", priceLevel.path()) 749 }, 750 "Operation is not allowed for final price level." 751 ); 752 } 753 List priceListEntries = this.getAssignedPriceListEntries( 754 priceLevel 755 ); 756 short processingMode = params.values("processingMode").size() > 0 757 ? ((Short )params.values("processingMode").get(0)).shortValue() 758 : 0; 759 List priceIdentitiesToBeRemoved = new ArrayList (); 763 List priceIdentitiesToBeUnlinked = new ArrayList (); 764 int numberProcessed = 0; 765 for( 766 Iterator i = priceListEntries.iterator(); 767 i.hasNext(); 768 ) { 769 DataproviderObject_1_0 priceListEntry = (DataproviderObject_1_0)i.next(); 770 if( 771 (processingMode == PROCESSING_MODE_PROCESS) && 772 (priceListEntry.values("basePrice").size() > 0) 773 ) { 774 if(priceListEntry.values("priceList").size() > 1) { 775 priceIdentitiesToBeUnlinked.add( 776 priceListEntry.values("basePrice").get(0) 777 ); 778 } 779 else { 780 priceIdentitiesToBeRemoved.add( 781 priceListEntry.values("basePrice").get(0) 782 ); 783 } 784 } 785 numberProcessed++; 786 } 787 for( 789 Iterator i = priceIdentitiesToBeRemoved.iterator(); 790 i.hasNext(); 791 ) { 792 this.plugin.removeObject((Path)i.next()); 793 } 794 for( 796 Iterator i = priceIdentitiesToBeUnlinked.iterator(); 797 i.hasNext(); 798 ) { 799 DataproviderObject price = this.plugin.retrieveObjectForModification( 800 (Path)i.next() 801 ); 802 price.values("priceList").remove( 803 priceLevel.path() 804 ); 805 } 806 return numberProcessed; 807 } 808 809 public int createInitialPrices( 811 ServiceHeader header, 812 DataproviderObject_1_0 priceLevel, 813 DataproviderObject_1_0 params 814 ) throws ServiceException { 815 if( 817 ((priceLevel.values("isFinal").size() > 0) && 818 ((Boolean )priceLevel.values("isFinal").get(0)).booleanValue()) 819 ) { 820 throw new ServiceException( 821 OpenCrxException.DOMAIN, 822 OpenCrxException.PRODUCT_OPERATION_NOT_ALLOWED_FOR_FINAL_PRICE_LEVEL, 823 new BasicException.Parameter[]{ 824 new BasicException.Parameter("param0", priceLevel.path()) 825 }, 826 "Operation is not allowed for final price level." 827 ); 828 } 829 if( 831 (priceLevel.values("priceCurrency").size() == 0) 832 ) { 833 throw new ServiceException( 834 OpenCrxException.DOMAIN, 835 OpenCrxException.PRODUCT_PRICE_LEVEL_MUST_HAVE_CURRENCY, 836 new BasicException.Parameter[]{ 837 new BasicException.Parameter("param0", priceLevel.path()) 838 }, 839 "Price level must have price uom and price currency." 840 ); 841 } 842 short processingMode = params.values("processingMode").size() > 0 843 ? ((Short )params.values("processingMode").get(0)).shortValue() 844 : 0; 845 846 List productFilter = new ArrayList (); 848 productFilter.addAll( 849 Arrays.asList( 850 this.getProductFilterProperties( 851 priceLevel.path() 852 ) 853 ) 854 ); 855 List allProducts = this.delegation.addFindRequest( 856 priceLevel.path().getPrefix(5).getChild("allProduct"), 857 (FilterProperty[])productFilter.toArray(new FilterProperty[productFilter.size()]), 858 AttributeSelectors.ALL_ATTRIBUTES, 859 0, 860 Integer.MAX_VALUE, 861 Directions.ASCENDING 862 ); 863 int numberProcessed = 0; 864 for( 865 Iterator i = allProducts.iterator(); 866 i.hasNext(); 867 ) { 868 DataproviderObject_1_0 product = (DataproviderObject_1_0)i.next(); 869 Path productIdentity = new Path((String )product.values(SystemAttributes.OBJECT_IDENTITY).get(0)); 870 List basePrices = this.findPrices( 871 priceLevel, 872 false, 873 productIdentity 874 ); 875 if(basePrices.size() == 0) { 876 DataproviderObject basePrice = new DataproviderObject( 877 productIdentity.getDescendant(new String []{"basePrice", this.plugin.getUidAsString()}) 878 ); 879 basePrice.values(SystemAttributes.OBJECT_CLASS).add("org:opencrx:kernel:product1:ProductBasePrice"); 880 basePrice.values("priceLevel").add( 881 priceLevel.path() 882 ); 883 basePrice.values("usage").addAll( 884 priceLevel.values("priceUsage") 885 ); 886 basePrice.values("price").add( 887 new BigDecimal (0) 888 ); 889 basePrice.values("priceCurrency").addAll( 890 priceLevel.values("priceCurrency") 891 ); 892 basePrice.values("discount").add( 893 new BigDecimal (0) 894 ); 895 basePrice.values("discountIsPercentage").add( 896 Boolean.FALSE 897 ); 898 basePrice.values("uom").addAll( 899 params.values("priceUom") 900 ); 901 if(processingMode == PROCESSING_MODE_PROCESS) { 902 this.delegation.addCreateRequest( 903 basePrice 904 ); 905 } 906 numberProcessed++; 907 } 908 } 909 return numberProcessed; 910 } 911 912 public void getPriceLevel( 914 ServiceHeader header, 915 DataproviderObject_1_0 pricingRule, 916 DataproviderObject_1_0 params, 917 DataproviderObject priceLevelResult 918 ) throws ServiceException { 919 try { 920 org.opencrx.kernel.product1.cci.GetPriceLevelResult res = 921 this.getPriceLevel( 922 (org.opencrx.kernel.product1.cci.PricingRule)this.rootPkg.refObject(pricingRule.path().toXri()), 923 params.values("contract").size() == 0 924 ? null 925 : (org.opencrx.kernel.contract1.cci.AbstractContract)this.rootPkg.refObject(((Path)params.values("contract").get(0)).toXri()), 926 params.values("product").size() == 0 927 ? null 928 : (org.opencrx.kernel.product1.cci.AbstractProduct)this.rootPkg.refObject(((Path)params.values("product").get(0)).toXri()), 929 params.values("priceUom").size() == 0 930 ? null 931 : (org.opencrx.kernel.uom1.cci.Uom)this.rootPkg.refObject(((Path)params.values("priceUom").get(0)).toXri()), 932 (BigDecimal )params.values("quantity").get(0), 933 params.values("pricingDate").size() == 0 934 ? null 935 : org.openmdx.base.text.format.DateFormat.getInstance().parse((String )params.values("pricingDate").get(0)) 936 ); 937 priceLevelResult.values("statusCode").add( 938 new Short (STATUS_CODE_OK) 939 ); 940 if(res != null) { 941 if(res.refDelegate().objGetValue("priceLevel") != null) { 942 priceLevelResult.values("priceLevel").add( 943 res.refDelegate().objGetValue("priceLevel") 944 ); 945 } 946 if(res.getDiscount() != null) { 947 priceLevelResult.values("discount").add( 948 res.getDiscount() 949 ); 950 } 951 if(res.isDiscountIsPercentage() != null) { 952 priceLevelResult.values("discountIsPercentage").add( 953 res.isDiscountIsPercentage() 954 ); 955 } 956 } 957 } 958 catch(ParseException e) { 959 priceLevelResult.values("statusCode").add( 960 new Short (STATUS_CODE_ERROR) 961 ); 962 priceLevelResult.values("statusMessage").add( 963 "Can not parse pricingDate" 964 ); 965 } 966 } 967 968 public org.opencrx.kernel.product1.cci.GetPriceLevelResult getPriceLevel( 970 org.opencrx.kernel.product1.cci.PricingRule pricingRule, 971 org.opencrx.kernel.contract1.cci.AbstractContract contract, 972 org.opencrx.kernel.product1.cci.AbstractProduct product, 973 org.opencrx.kernel.uom1.cci.Uom priceUom, 974 BigDecimal quantity, 975 Date pricingDate 976 ) throws ServiceException { 977 String script = (pricingRule.getGetPriceLevelScript() == null) || (pricingRule.getGetPriceLevelScript().length() == 0) 978 ? DEFAULT_GET_PRICE_LEVEL_SCRIPT 979 : pricingRule.getGetPriceLevelScript(); 980 org.opencrx.kernel.product1.cci.product1Package productPkg = 981 (org.opencrx.kernel.product1.cci.product1Package)rootPkg.refPackage( 982 org.opencrx.kernel.product1.cci.product1Package.class.getName() 983 ); 984 try { 985 Class c = new ClassBodyEvaluator(script).evaluate(); 986 Method m = c.getMethod( 987 "getPriceLevel", 988 new Class [] { 989 org.openmdx.base.accessor.jmi.cci.RefPackage_1_0.class, 990 org.opencrx.kernel.product1.cci.PricingRule.class, 991 org.opencrx.kernel.contract1.cci.AbstractContract.class, 992 org.opencrx.kernel.product1.cci.AbstractProduct.class, 993 org.opencrx.kernel.uom1.cci.Uom.class, 994 java.math.BigDecimal .class, 995 java.util.Date .class 996 } 997 ); 998 return (org.opencrx.kernel.product1.cci.GetPriceLevelResult)m.invoke( 999 null, 1000 new Object [] { 1001 this.rootPkg, 1002 pricingRule, 1003 contract, 1004 product, 1005 priceUom, 1006 quantity, 1007 pricingDate 1008 } 1009 ); 1010 } 1011 catch(CompileException e) { 1012 return productPkg.createGetPriceLevelResult( 1013 null, null, null, 1014 STATUS_CODE_ERROR, 1015 "Can not compile getPriceLevelScript:\n" + 1016 e.getMessage() 1017 ); 1018 } 1019 catch(Parser.ParseException e) { 1020 return productPkg.createGetPriceLevelResult( 1021 null, null, null, 1022 STATUS_CODE_ERROR, 1023 "Can not parse getPriceLevelScript:\n" + 1024 e.getMessage() 1025 ); 1026 } 1027 catch(Scanner.ScanException e) { 1028 return productPkg.createGetPriceLevelResult( 1029 null, null, null, 1030 STATUS_CODE_ERROR, 1031 "Can not scan getPriceLevelScript:\n" + 1032 e.getMessage() 1033 ); 1034 } 1035 catch(NoSuchMethodException e) { 1036 return productPkg.createGetPriceLevelResult( 1037 null, null, null, 1038 STATUS_CODE_ERROR, 1039 "getPriceLevelScript does not define a method with the following signature:\n" + 1040 DEFAULT_GET_PRICE_LEVEL_SCRIPT 1041 ); 1042 } 1043 catch(InvocationTargetException e) { 1044 return productPkg.createGetPriceLevelResult( 1045 null, null, null, 1046 STATUS_CODE_ERROR, 1047 "Can not invoke getPriceLevel():\n" + 1048 e.getTargetException().getMessage() 1049 ); 1050 } 1051 catch(IllegalAccessException e) { 1052 return productPkg.createGetPriceLevelResult( 1053 null, null, null, 1054 STATUS_CODE_ERROR, 1055 "Illegal access when invoking getPriceLevel():\n" + 1056 e.getMessage() 1057 ); 1058 } 1059 } 1060 1061 private boolean isBasedOnPriceLevel( 1063 Path priceLevelIdentity 1064 ) throws ServiceException { 1065 List dependingPriceLevels = this.delegation.addFindRequest( 1066 priceLevelIdentity.getParent(), 1067 new FilterProperty[]{ 1068 new FilterProperty( 1069 Quantors.THERE_EXISTS, 1070 "basedOn", 1071 FilterOperators.IS_IN, 1072 new Object []{priceLevelIdentity} 1073 ) 1074 } 1075 ); 1076 return dependingPriceLevels.size() > 0; 1077 } 1078 1079 public void removePriceLevel( 1081 ServiceHeader header, 1082 Path priceLevelIdentity 1083 ) throws ServiceException { 1084 if(this.isBasedOnPriceLevel(priceLevelIdentity)) { 1085 throw new ServiceException( 1086 OpenCrxException.DOMAIN, 1087 OpenCrxException.PRODUCT_OPERATION_NOT_ALLOWED_FOR_BASEDON_PRICE_LEVEL, 1088 new BasicException.Parameter[]{ 1089 new BasicException.Parameter("param0", priceLevelIdentity) 1090 }, 1091 "Can not delete price level. Other price levels are based on this price level." 1092 ); 1093 } 1094 List priceListEntries = this.delegation.addFindRequest( 1096 priceLevelIdentity.getPrefix(5).getChild("priceListEntry"), 1097 new FilterProperty[]{ 1098 new FilterProperty( 1099 Quantors.THERE_EXISTS, 1100 "priceLevel", 1101 FilterOperators.IS_IN, 1102 new Object []{priceLevelIdentity} 1103 1104 ) 1105 } 1106 ); 1107 if(priceListEntries.size() > 0) { 1108 throw new ServiceException( 1109 OpenCrxException.DOMAIN, 1110 OpenCrxException.PRODUCT_OPERATION_NOT_ALLOWED_FOR_PRICE_LEVEL_HAVING_PRICES, 1111 new BasicException.Parameter[]{ 1112 new BasicException.Parameter("param0", priceLevelIdentity) 1113 }, 1114 "Can not delete price level. Price level has assigned prices." 1115 ); 1116 } 1117 DataproviderObject_1_0 priceLevel = this.plugin.retrieveObjectFromDelegation(priceLevelIdentity); 1118 if( 1119 (priceLevel.values("isFinal").size() > 0) && 1120 ((Boolean )priceLevel.values("isFinal").get(0)).booleanValue() 1121 ) { 1122 throw new ServiceException( 1123 OpenCrxException.DOMAIN, 1124 OpenCrxException.PRODUCT_OPERATION_NOT_ALLOWED_FOR_FINAL_PRICE_LEVEL, 1125 new BasicException.Parameter[]{ 1126 new BasicException.Parameter("param0", priceLevel.path()) 1127 }, 1128 "Can not delete final price level." 1129 ); 1130 } 1131 this.plugin.removeObject(priceLevel.path()); 1132 } 1133 1134 private final static int BATCHING_MODE_SIZE = 1000; 1138 1139 private static final short PROCESSING_MODE_NA = 0; 1140 private static final short PROCESSING_MODE_TEST = 1; 1141 private static final short PROCESSING_MODE_PROCESS = 2; 1142 1143 private final static short STATUS_CODE_OK = 0; 1144 private final static short STATUS_CODE_ERROR = 1; 1145 1146 private static final String DEFAULT_GET_PRICE_LEVEL_SCRIPT = 1147 "public static org.opencrx.kernel.product1.cci.GetPriceLevelResult getPriceLevel(\n" + 1148 "org.openmdx.base.accessor.jmi.cci.RefPackage_1_0 rootPkg,\n" + 1149 "org.opencrx.kernel.product1.cci.PricingRule pricingRule,\n" + 1150 "org.opencrx.kernel.contract1.cci.AbstractContract contract,\n" + 1151 "org.opencrx.kernel.product1.cci.AbstractProduct product,\n" + 1152 "org.opencrx.kernel.uom1.cci.Uom priceUom,\n" + 1153 "java.math.BigDecimal quantity,\n" + 1154 "java.util.Date pricingDate\n" + 1155 ") {\n" + 1156 "org.opencrx.kernel.product1.cci.product1Package productPkg =\n" + 1157 "(org.opencrx.kernel.product1.cci.product1Package)rootPkg.refPackage(\n" + 1158 "org.opencrx.kernel.product1.cci.product1Package.class.getName()\n" + 1159 ");\n" + 1160 "org.opencrx.kernel.product1.cci.GetPriceLevelResult result = productPkg.createGetPriceLevelResult(\n" + 1161 "null,\n" + 1162 "null,\n" + 1163 "null,\n" + 1164 "(short)0,\n" + 1165 "null\n" + 1166 ");\n" + 1167 "return result;\n" + 1168 "}"; 1169 1170 private final Model_1_0 model; 1171 private final OpenCrxKernel_1 plugin; 1172 private final RequestCollection delegation; 1173 private final RefPackage_1_0 rootPkg; 1174 1175} 1176 1177 | Popular Tags |