· 4 years ago · Jul 22, 2021, 11:18 AM
1package org.jleaf.erp.sls.bo.salesorderbybrand;
2
3import java.text.NumberFormat;
4import java.util.ArrayList;
5import java.util.List;
6
7import javax.persistence.Query;
8
9import org.jleaf.common.CommonExceptionConstants;
10import org.jleaf.core.BusinessFunction;
11import org.jleaf.core.BusinessTransaction;
12import org.jleaf.core.CoreException;
13import org.jleaf.core.DefaultBusinessTransaction;
14import org.jleaf.core.Dto;
15import org.jleaf.core.GeneralConstants;
16import org.jleaf.core.annotation.ErrorList;
17import org.jleaf.core.annotation.Info;
18import org.jleaf.core.annotation.InfoIn;
19import org.jleaf.core.annotation.InfoOut;
20import org.jleaf.core.dao.QueryBuilder;
21import org.jleaf.erp.inv.dao.ProductBalanceStockReservedDao;
22import org.jleaf.erp.master.MasterExceptionConstants;
23import org.jleaf.erp.sls.SalesConstants;
24import org.jleaf.erp.sls.SalesConstantsForKtmt;
25import org.jleaf.erp.sls.SalesExceptionConstants;
26import org.jleaf.erp.sls.SalesExceptionConstantsForKtmt;
27import org.jleaf.erp.sls.dao.LogProductBalanceStockReservedDao;
28import org.jleaf.erp.sls.dao.MouBalanceDao;
29import org.jleaf.erp.sls.dao.MouBalanceLogDao;
30import org.jleaf.erp.sls.dao.SalesOrderDao;
31import org.jleaf.erp.sls.dao.SoBrandItemDao;
32import org.jleaf.erp.sls.dao.SoInfoDao;
33import org.jleaf.erp.sls.dao.SoStatusDao;
34import org.jleaf.erp.sls.entity.LogProductBalanceStockReserved;
35import org.jleaf.erp.sls.entity.MouBalance;
36import org.jleaf.erp.sls.entity.MouBalanceLog;
37import org.jleaf.erp.sls.entity.SalesOrder;
38import org.jleaf.erp.sls.entity.SalesOrderItem;
39import org.jleaf.erp.sls.entity.SoBrandItem;
40import org.jleaf.erp.sls.entity.SoInfo;
41import org.jleaf.erp.sls.entity.SoStatus;
42import org.jleaf.util.Calc;
43import org.jleaf.util.DateUtil;
44import org.jleaf.util.DtoUtil;
45import org.jleaf.util.GsonUtil;
46import org.jleaf.util.ValidationUtil;
47import org.jleaf.validator.CommonBusinessValidator;
48import org.slf4j.Logger;
49import org.slf4j.LoggerFactory;
50import org.springframework.beans.factory.annotation.Autowired;
51import org.springframework.beans.factory.annotation.Qualifier;
52import org.springframework.stereotype.Service;
53
54/**
55 *
56 * Henik, Sep 18, 2015
57 *
58**/
59//@formatter:off
60@Service
61@InfoIn(value = {
62 @Info(name = "id", description = "sales order by brand id", type = Long.class),
63 @Info(name = "version", description = "sales order version", type = Long.class),
64 @Info(name = "workflowStatus", description = "Workflow Status", type = String.class),
65 @Info(name = "tenantLoginId", description = "tenant login id", type = Long.class),
66 @Info(name = "userLoginId", description = "user login id", type = Long.class),
67 @Info(name = "roleLoginId", description = "role login id", type = Long.class),
68 @Info(name = "datetime", description = "datetime", type = String.class)
69})
70@InfoOut(value = {
71 @Info(name = "id", description = "so by brand id", type = Long.class),
72 @Info(name = "tenantId", description = "tenant id", type = Long.class),
73 @Info(name = "docTypeId", description = "doc type id", type = Long.class),
74 @Info(name = "docNo", description = "Nomor Transaksi", type = String.class),
75 @Info(name = "docDate", description = "Tanggal Transaksi", type = String.class),
76 @Info(name = "ouId", description = "Organisasi Unit id", type = Long.class),
77 @Info(name = "extDocNo", description = "external document no", type = String.class),
78 @Info(name = "extDocDate", description = "external document date", type = String.class),
79 @Info(name = "refDocTypeId", description = "ref doc type id", type = Long.class),
80 @Info(name = "reId", description = "ref id", type = Long.class),
81 @Info(name = "remark", description = "remark", type = String.class),
82 @Info(name = "partnerId", description = "partner id", type = Long.class),
83 @Info(name = "partnerCpId", description = "partner contact person id", type = Long.class),
84 @Info(name = "partnerBillToId", description = "partner bill to id", type = Long.class),
85 @Info(name = "dueDate", description = "due date", type = String.class),
86 @Info(name = "salesmanId", description = "salesman id", type = Long.class),
87 @Info(name = "flgDelivery", description = "flag delivery (pick up or deliver)", type = String.class),
88 @Info(name = "currCode", description = "currency code", type = String.class),
89 @Info(name = "addDiscountPercentage", description = "add discount percentage", type = Double.class),
90 @Info(name = "addDiscountAmount", description = "add discount amount", type = Double.class),
91 @Info(name = "partnerShipToId", description = "Partner Ship To id", type = Long.class),
92 @Info(name = "partnerShipAddressId", description = "Partner Ship address id", type = Long.class),
93
94 @Info(name = "flgWorkOrder", description = "Flag work order", type = String.class),
95 @Info(name = "flgShowInvTax", description = "Flag Show Inv Tax", type = String.class, required = false),
96 @Info(name = "flgTopType", description = "Flag top type", type = String.class),
97 @Info(name = "partnerShipCpId", description = "Partner Ship CP id", type = Long.class),
98 @Info(name = "partnerShipCpName", description = "Partner Ship CP name", type = String.class),
99 @Info(name = "partnerShipCpPhone1", description = "Partner Ship CP phone1", type = String.class),
100 @Info(name = "partnerShipCpPhone2", description = "Partner Ship CP phone2", type = String.class),
101
102 @Info(name = "statusDoc", description = "status doc", type = String.class, required = true),
103 @Info(name = "workflowStatus", description = "workflow status", type = String.class, required = true),
104 @Info(name = "createUserId", description = "Create user id", type = Long.class, required = true),
105 @Info(name = "createDateTime", description = "Create date time", type = String.class, required = true),
106 @Info(name = "updateUserId", description = "Update user id", type = Long.class, required = true),
107 @Info(name = "updateDateTime", description = "Update date time", type = String.class, required = true),
108 @Info(name = "version", description = "Version", type = Long.class, required = true)
109})
110@ErrorList(errorKeys = {
111 CommonExceptionConstants.TENANT_LOGIN_CANT_USED,
112 CommonExceptionConstants.DATA_CANT_CHANGE_CAUSE_TENANT,
113 SalesExceptionConstants.SALES_ORDER_ID_NOT_FOUND,
114 SalesExceptionConstants.SALES_ORDER_MUST_HAVE_AT_LEAST_ONE_DETAIL_ITEM,
115 SalesExceptionConstantsForKtmt.SO_DATE_NOT_VALID_TO_MOU,
116 SalesExceptionConstantsForKtmt.SO_DATE_NOT_VALID_TO_PRODUCT_LAUNCHING,
117 SalesExceptionConstantsForKtmt.SO_DATE_NOT_VALID_TO_PROMO,
118 SalesExceptionConstantsForKtmt.CANT_USE_THIS_BRAND_FOR_DATA_FOC_CAUSE_SUB_CATEGORY_PRODUCT_NOT_VALID
119})
120//@formatter:on
121public class SubmitSalesOrderByBrand extends DefaultBusinessTransaction implements BusinessTransaction {
122
123 private static final Logger log = LoggerFactory.getLogger(SubmitSalesOrderByBrand.class);
124
125 @Autowired
126 private SalesOrderDao salesOrderDao;
127
128 @Autowired
129 private SoBrandItemDao soBrandItemDao;
130
131 @Autowired
132 private SoInfoDao soInfoDao;
133
134 @Autowired
135 private SoStatusDao soStatusDao;
136
137 @Autowired
138 private ProductBalanceStockReservedDao productBalanceStockReservedDao;
139
140 @Autowired
141 private LogProductBalanceStockReservedDao logProductBalanceStockReservedDao;
142
143 @Autowired
144 private MouBalanceDao mouBalanceDao;
145
146 @Autowired
147 private MouBalanceLogDao mouBalanceLogDao;
148
149 @Autowired
150 @Qualifier("findSalesOrderById")
151 private BusinessFunction findSalesOrderById;
152
153 @Autowired
154 @Qualifier("valTenantLoginCanUse")
155 private BusinessFunction valTenantLoginCanUse;
156
157 @Autowired
158 @Qualifier("getSalesOrderDetailBrandListBySalesOrder")
159 private BusinessFunction getSalesOrderDetailBrandListBySalesOrder;
160
161 @Autowired
162 @Qualifier("findSoInfoByIndex")
163 private BusinessFunction findSoInfoByIndex;
164
165 @Autowired
166 @Qualifier("findMouById")
167 private BusinessFunction findMouById;
168
169 @Autowired
170 @Qualifier("findSoBrandItemById")
171 private BusinessFunction findSoBrandItemById;
172
173 @Autowired
174 @Qualifier("valMouValidToSalesOrder")
175 private BusinessFunction valMouValidToSalesOrder;
176
177 @Autowired
178 @Qualifier("findMouBalanceById")
179 private BusinessFunction findMouBalanceById;
180
181 @Autowired
182 @Qualifier("findPromoById")
183 private BusinessFunction findPromoById;
184
185 @Autowired
186 @Qualifier("valPromoValidToSalesOrder")
187 private BusinessFunction valPromoValidToSalesOrder;
188
189 @Autowired
190 @Qualifier("isDifferentGroupBrandExistsByBrandList")
191 private BusinessFunction isDifferentGroupBrandExistsByBrandList;
192
193 @Autowired
194 @Qualifier("isSoBrandValidToCreateAutomaticSettlement")
195 private BusinessFunction isSoBrandValidToCreateAutomaticSettlement;
196
197 @Autowired
198 @Qualifier("isQtySoBrandValidToCreateAutomaticSettlement")
199 private BusinessFunction isQtySoBrandValidToCreateAutomaticSettlement;
200
201 @Autowired
202 @Qualifier("isQtySoBrandAndQtySoItemValidToCreateAutomaticSettlement")
203 private BusinessFunction isQtySoBrandAndQtySoItemValidToCreateAutomaticSettlement;
204
205 @Autowired
206 @Qualifier("findParentOUMainBuByOu")
207 private BusinessFunction findParentOUMainBuByOu;
208
209 @Autowired
210 @Qualifier("isOULegalExistsByIndex")
211 private BusinessFunction isOULegalExistsByIndex;
212
213 @Autowired
214 @Qualifier("findOUById")
215 private BusinessFunction findOUById;
216
217 @Autowired
218 @Qualifier("valQtyBrandSoByBrandId")
219 private BusinessFunction valQtyBrandSoByBrandId;
220
221 @Autowired
222 @Qualifier("findSoStatusById")
223 private BusinessFunction findSoStatusById;
224
225 @Autowired
226 @Qualifier("findParameterByIndex")
227 private BusinessFunction findParameterByIndex;
228
229 @Autowired
230 @Qualifier("isSystemConfigExistsByIndex")
231 private BusinessFunction isSystemConfigExistsByIndex;
232
233 @Autowired
234 @Qualifier("isSoBrandItemFOCAndNonFOCExistsBySOB")
235 private BusinessFunction isSoBrandItemFOCAndNonFOCExistsBySOB;
236
237 @Autowired
238 @Qualifier("getSubCtgrProductListFromDataFOCSalesOrderByBrand")
239 private BusinessFunction getSubCtgrProductListFromDataFOCSalesOrderByBrand;
240
241 @Autowired
242 @Qualifier("isSoBrandValidToCreateDataFOC")
243 private BusinessFunction isSoBrandValidToCreateDataFOC;
244
245 @Autowired
246 @Qualifier("isNotValidTaggingForSOBExists")
247 private BusinessFunction isNotValidTaggingForSOBExists;
248
249 @Autowired
250 @Qualifier("findBrandById")
251 private BusinessFunction findBrandById;
252
253 @Autowired
254 @Qualifier("valSoBrandItemValidToTagging")
255 private BusinessFunction valSoBrandItemValidToTagging;
256
257 @Autowired
258 @Qualifier("getSalesOrderDetailItemListBySalesOrder")
259 private BusinessFunction getSalesOrderDetailItemListBySalesOrder;
260
261 @Autowired
262 @Qualifier("isQtySKUSoByProductId")
263 private BusinessFunction isQtySKUSoByProductId;
264
265 private void checkTenant(Long tenantLoginId, Dto dto, String desc1, String desc2) {
266 if (!tenantLoginId.equals(dto.getLong("tenantId"))) {
267 throw new CoreException(CommonExceptionConstants.DATA_CANT_CHANGE_CAUSE_TENANT, desc1, desc2);
268 }
269 }
270
271 private void checkActive(Dto dto, String desc) {
272 if (!GeneralConstants.YES.equals(dto.getString("active"))) {
273 throw new CoreException(MasterExceptionConstants.DATA_NOT_ACTIVE, desc);
274 }
275 }
276
277 @Override
278 public String getDescription() {
279 return "Submit Sales Order By Brand";
280 }
281
282 @SuppressWarnings({ "unchecked", "unused" })
283 @Override
284 public Dto prepare(Dto inputDto, Dto originalDto) throws Exception {
285 log.debug(" Start prepare SubmitSalesOrderByBrand() : "+DateUtil.dateTimeNow());
286
287 // validasi parameter input
288 ValidationUtil.valBlankOrNull(inputDto, "id");
289 ValidationUtil.valBlankOrNull(inputDto, "workflowStatus");
290 ValidationUtil.valBlankOrNull(inputDto, "version");
291
292 ValidationUtil.valBlankOrNull(inputDto, "tenantLoginId");
293 ValidationUtil.valBlankOrNull(inputDto, "userLoginId");
294 ValidationUtil.valBlankOrNull(inputDto, "roleLoginId");
295 ValidationUtil.valDatetime(inputDto, "datetime");
296
297 // penamaan variable
298 Long id = inputDto.getLong("id");
299 Long version = inputDto.getLong("version");
300 String workflowStatus = inputDto.getString("workflowStatus");
301 Long tenantLoginId = inputDto.getLong("tenantLoginId");
302 Long userLoginId = inputDto.getLong("userLoginId");
303 Long roleLoginId = inputDto.getLong("roleLoginId");
304 String datetime = inputDto.getString("datetime");
305 boolean needValidationQty = false;
306
307 // Validation tenant login id can be use
308 Dto loginDto = new Dto();
309 loginDto.put("tenantLoginId", tenantLoginId);
310 loginDto.put("userLoginId", userLoginId);
311 loginDto.put("roleLoginId", roleLoginId);
312 valTenantLoginCanUse.execute(loginDto);
313
314 // Data header Sales Order by Brand harus ada di sistem
315 Dto salesOrderByBrandDto = findSalesOrderById.execute(new Dto().put("id", id));
316 Long ouId = salesOrderByBrandDto.getLong("ouId");
317 Long partnerId = salesOrderByBrandDto.getLong("partnerId");
318 String docDate = salesOrderByBrandDto.getString("docDate");
319 String docNo = salesOrderByBrandDto.getString("docNo");
320 Long salesmanId = salesOrderByBrandDto.getLong("salesmanId");
321
322 // cek tenant id so by brand dengan tenantLoginId harus sama
323 checkTenant(tenantLoginId, salesOrderByBrandDto, "tenant id", "Sales Order By Brand");
324
325 // validate version
326 if (!salesOrderByBrandDto.getLong("version").equals(version)) {
327 throw new CoreException(SalesExceptionConstants.DOCUMENT_VERSION_NOT_UPTODATE);
328 }
329
330 // validation draft document
331 if (!SalesConstants.DRAFT_TRANSACTION.equals(salesOrderByBrandDto.getString("statusDoc"))) {
332 throw new CoreException(SalesExceptionConstants.DOC_ALREADY_SUBMITTED);
333 }
334
335 if(salesmanId.equals(SalesConstantsForKtmt.NULL_VALUE_LONG)) {
336 throw new CoreException(SalesExceptionConstantsForKtmt.SALESMAN_ID_EMPTY);
337 }
338
339 Dto paramValidateBrand = new Dto();
340 paramValidateBrand.put("soId", id);
341 paramValidateBrand.put("tenantId", salesOrderByBrandDto.getLong("tenantId"));
342 Dto isBrandValidDto = isSoBrandValidToCreateAutomaticSettlement.execute(paramValidateBrand);
343 Dto isQtyBrandValidDto = isQtySoBrandValidToCreateAutomaticSettlement.execute(paramValidateBrand);
344 Dto isQtySoBrandAndQtySoItemValidDto = isQtySoBrandAndQtySoItemValidToCreateAutomaticSettlement.execute(paramValidateBrand);
345
346 // Pengecekan untuk menentukan, perlu/tidak lakukan validasi qty SOB
347 if (isBrandValidDto.getBoolean("exists") && !isQtyBrandValidDto.getBoolean("exists")) {
348 throw new CoreException(SalesExceptionConstantsForKtmt.SOME_BRAND_NEED_TO_BE_DEFINE_THE_PRODUCT_ITEM);
349 } else if (isBrandValidDto.getBoolean("exists") && isQtyBrandValidDto.getBoolean("exists")) {
350 needValidationQty = true;
351 } else if (isQtySoBrandAndQtySoItemValidDto.getBoolean("valid")) {
352 needValidationQty = true;
353 }
354
355 // validasi tanggal dokumen <= tanggal hari ini
356 CommonBusinessValidator.valCompareDate(docDate, DateUtil.dateNow(), CommonBusinessValidator.COMPARE_LESS_EQUAL,
357 "Doc Date For Submit", "Today");
358
359 //get SO Info
360 Dto soInfoDto = findSoInfoByIndex.execute(new Dto().put("tenantId", tenantLoginId).put("soId", id));
361 Long mouId = soInfoDto.getLong("mouId");
362 Long promoId = soInfoDto.getLong("promoId");
363 Long productLaunchingId = soInfoDto.getLong("productLaunchingId");
364 String flgTypeSo = soInfoDto.getString("flgTypeSo");
365
366 // akan di gunakan di method process
367 inputDto.put("mouId", mouId);
368
369 Dto detailBrandListDto = getSalesOrderDetailBrandListBySalesOrder.execute(new Dto().put("tenantId", tenantLoginId).put(
370 "soId", id));
371 List<Dto> salesOrderDetailBrandList = detailBrandListDto.getList("salesOrderDetailBrandList");
372 Calc nettAmount = new Calc(0);
373 Calc nettAmountIncludeTax = new Calc(0);
374 List<Dto> brandItemList = new ArrayList<Dto>();
375 List<Dto> brandList = new ArrayList<Dto>();
376 List<Dto> failList = new ArrayList<Dto>();
377
378 log.debug(" Start Cek DetaiBrand() : "+DateUtil.dateTimeNow());
379 if (salesOrderDetailBrandList == null || salesOrderDetailBrandList.isEmpty()) {
380 throw new CoreException(SalesExceptionConstantsForKtmt.SALES_ORDER_BY_BRAND_MUST_HAVE_AT_LEAST_ONE_DETAIL_BRAND);
381 } else {
382 Long generateLineNo = new Long(0);
383
384 log.debug(" prepare looping brand item detail () : "+DateUtil.dateTimeNow());
385 for (Dto itemDetailBrand : salesOrderDetailBrandList) {
386 try {
387 Double price = Double.parseDouble(itemDetailBrand.getString("grossSellPrice"));
388 Long soBrandItemId = Long.parseLong(itemDetailBrand.getString("soBrandItemId"));
389 Long brandId = Long.parseLong(itemDetailBrand.getString("brandId"));
390 Long taxId = Long.parseLong(itemDetailBrand.getString("taxId"));
391 Double qty = itemDetailBrand.getDouble("qty");
392
393 // generate untuk nilai lineNo
394 generateLineNo = new Calc(generateLineNo).add(1).longValue();
395
396 // Menampung brandId kedalam list dto untuk keperluan validasi mengenai group brand
397 Dto valBrandDto = new Dto();
398 valBrandDto.put("brandId", brandId);
399 brandList.add(valBrandDto);
400
401 /*
402 * Validasi stock qty per brand harus mencukupi tidak hanya ketika automatic SOS.
403 * Jadi setiap submit SOB harus selalu dicek stock qty per brand harus masih cukup.
404 */
405 valQtyBrandSoByBrandId.execute(new Dto()
406 .put("ouId", ouId)
407 .put("brandId", brandId)
408 .put("qty", qty)
409 );
410
411 // Cek Data OU
412 Dto ouDto = findOUById.execute(new Dto().put("id", salesOrderByBrandDto.getLong("ouId")));
413
414 Dto outputOuBuDto = findParentOUMainBuByOu.execute(new Dto().put("id", ouDto.get("id")));
415
416 Dto outputIsOULegalExistsByIndex = isOULegalExistsByIndex.execute(new Dto().put("tenantId", ouDto.get("tenantId")).put(
417 "ouId", outputOuBuDto.getLong("id")));
418
419 if (outputIsOULegalExistsByIndex.getBoolean("exists")) {
420 Dto ouLegalDto = outputIsOULegalExistsByIndex.getDto("ouLegalDto");
421
422 if (GeneralConstants.YES.equals(ouLegalDto.getString("flgPkp"))) {
423
424 // Validasi mengenai tax akan dijalankan jika flg PKP nya = Y
425 NumberFormat formatter = NumberFormat.getNumberInstance();
426 formatter.setMinimumFractionDigits(1); // 1 angka di belakang komaf
427 String formattedPrice = formatter.format(price);
428 String zero = formatter.format(new Double(0));
429
430 if (GeneralConstants.NULL_REF_VALUE_LONG.equals(taxId)) {
431 // Jika taxId = -99 -> price nya harus = 0
432 boolean isValidPriceMustZero = CommonBusinessValidator.compareNumber(price.toString(), "0",
433 CommonBusinessValidator.COMPARE_EQUAL, "Price", "0");
434
435 if (!isValidPriceMustZero) {
436 throw new CoreException(
437 SalesExceptionConstantsForKtmt.PRICE_MUST_BE_EQUAL_ZERO_CAUSE_YOU_NOT_CHOOSE_THE_TAX,
438 formattedPrice, zero);
439 }
440
441 } else {
442 // Jika taxId != -99 -> price nya harus > 0
443 boolean isValidPriceDontZero = CommonBusinessValidator.compareNumber(price.toString(), "0",
444 CommonBusinessValidator.COMPARE_GREATER, "Price", "0");
445
446 if (!isValidPriceDontZero) {
447 throw new CoreException(
448 SalesExceptionConstantsForKtmt.PRICE_MUST_BE_GREATER_THAN_ZERO_CAUSE_YOU_CHOOSE_THE_TAX,
449 formattedPrice, zero);
450 }
451 }
452 }
453 }
454
455 // ambil data brand
456 Dto brandDto = findBrandById.execute(new Dto().put("id", brandId));
457 checkTenant(tenantLoginId, brandDto, "Sales Order Brand Item", "Brand");
458 checkActive(brandDto, "Brand");
459
460 StringBuilder brandCodeName = new StringBuilder();
461 brandCodeName.append(brandDto.get("code"));
462 brandCodeName.append(" - ");
463 brandCodeName.append(brandDto.get("name"));
464
465 // validasi brandId of brand SOB jika ada tagging ke Launching/Promo/MOU
466 Dto paramInputValSoBrandValidToTaggingDto = new Dto();
467 paramInputValSoBrandValidToTaggingDto.put("brandId", brandId);
468 paramInputValSoBrandValidToTaggingDto.put("brandCodeName", brandCodeName.toString());
469 paramInputValSoBrandValidToTaggingDto.put("soDate", docDate);
470 paramInputValSoBrandValidToTaggingDto.put("productLaunchingId", productLaunchingId);
471 paramInputValSoBrandValidToTaggingDto.put("promoId", promoId);
472 paramInputValSoBrandValidToTaggingDto.put("mouId", mouId);
473 valSoBrandItemValidToTagging.execute(paramInputValSoBrandValidToTaggingDto);
474
475 // noted : nilai nettBrandAmount dari BF ini sudah include tax
476 nettAmount = nettAmount.add(itemDetailBrand.getDouble("nettBrandAmount"));
477
478 Dto brandItemDto = findSoBrandItemById.execute(new Dto().put("id", soBrandItemId));
479 // update lineNo di table_sl_so_brand_item
480 brandItemDto.put("lineNo", generateLineNo);
481 this.prepareUpdateAudit(brandItemDto, userLoginId, datetime);
482
483 // tampung dalam list
484 brandItemList.add(brandItemDto);
485 } catch (CoreException e) {
486 Dto inputDtoforCekQty = (Dto) itemDetailBrand.clone();
487 // success dto
488 inputDtoforCekQty.put("errorKey", e.getErrorKey());
489
490 List<Object> argsList = new ArrayList<Object>();
491 if (e.getParamValues() != null && e.getParamValues().length > 0)
492 for (Object paramValue : e.getParamValues()) {
493 argsList.add(paramValue);
494 }
495 inputDtoforCekQty.put("args", argsList);
496
497 failList.add(inputDtoforCekQty);
498 }
499 }
500 log.debug(" end looping brand item detail () : "+DateUtil.dateTimeNow());
501 }
502 log.debug(" End Cek DetaiBrand() : "+DateUtil.dateTimeNow());
503
504 if (!failList.isEmpty()) {
505 Dto errorParamDto = new Dto();
506 DtoUtil.putInErrorParamDto(errorParamDto, "failList", new String[] { "brandCode","brandName","qty","errorKey", "args" }, failList);
507 throw new CoreException(SalesExceptionConstantsForKtmt.SALES_ORDER_BRAND_ITEMS_ERROR, errorParamDto, docNo, id);
508 }
509
510 // Calculasi total amount sob
511 nettAmountIncludeTax = nettAmountIncludeTax.add(nettAmount);
512
513 // Cek data SKU mengenai stock
514 Dto detailItemListDto = getSalesOrderDetailItemListBySalesOrder.execute(new Dto().put("tenantId", tenantLoginId).put(
515 "soId", id));
516
517 List<Dto> failItemList = new ArrayList<Dto>();
518 List<Dto> salesOrderDetailItemList = detailItemListDto.getList("salesOrderDetailItemList");
519 List<Dto> mergeDataStockReservedList = new ArrayList<Dto>();
520
521 log.debug(" Start Cek DetaiItem() : "+DateUtil.dateTimeNow());
522 if(salesOrderDetailItemList != null && salesOrderDetailItemList.size() > 0){
523
524 log.debug(" start looping item detail () : "+DateUtil.dateTimeNow());
525 for (Dto salesOrderDetailItemDto : salesOrderDetailItemList) {
526 try {
527 Double qtyInt = Double.parseDouble(salesOrderDetailItemDto.getDouble("qtyInt").toString());
528 Long productId = Long.parseLong(salesOrderDetailItemDto.getString("productId").toString());
529
530 // Cek stock nya masih cukup atau tidak untuk SKU ini
531 Dto resultValQty = isQtySKUSoByProductId.execute(new Dto()
532 .put("ouId", ouId)
533 .put("productId", productId)
534 .put("qty", qtyInt)
535 );
536
537 if (!resultValQty.getBoolean("valid")) {
538 Dto soItemDto = resultValQty.getDto("soItemDto");
539 salesOrderDetailItemDto.put("errorForRemarkSettlement",
540 salesOrderDetailItemDto.getString("productName").concat(", req ").concat(qtyInt.toString())
541 .concat(", stock ").concat(soItemDto.getDouble("balanceQty").toString()));
542
543 throw new CoreException(SalesExceptionConstantsForKtmt.INSUFFICIENT_STOCK_AFTER_CALCULATE_QTY_SKU,
544 soItemDto.getString("productName"), soItemDto.getDouble("balanceQty"));
545 }
546
547 // Tampung data detail so item, untuk dilakukan update stock reserved
548 mergeDataStockReservedList.add(salesOrderDetailItemDto);
549
550 } catch (CoreException e) {
551 Dto inputDtoforCekQtySku = (Dto) salesOrderDetailItemDto.clone();
552 // success dto
553 inputDtoforCekQtySku.put("errorKey", e.getErrorKey());
554
555 List<Object> argsList = new ArrayList<Object>();
556 if (e.getParamValues() != null && e.getParamValues().length > 0)
557 for (Object paramValue : e.getParamValues()) {
558 argsList.add(paramValue);
559 }
560 inputDtoforCekQtySku.put("args", argsList);
561
562 failItemList.add(inputDtoforCekQtySku);
563
564 }
565 }
566 log.debug(" end looping item detail () : "+DateUtil.dateTimeNow());
567 }
568 log.debug(" End Cek DetaiItem() : "+DateUtil.dateTimeNow());
569
570 if (!failItemList.isEmpty()) {
571 Dto errorParamDto = new Dto();
572 DtoUtil.putInErrorParamDto(errorParamDto, "failList", new String[] { "errorForRemarkSettlement", "args" }, failItemList);
573 throw new CoreException(SalesExceptionConstantsForKtmt.SALES_ORDER_ITEMS_ERROR, errorParamDto, docNo, id);
574 }
575
576 log.debug(" Start Cek GroupBrand() : "+DateUtil.dateTimeNow());
577 // Validasi : bahwa dalam 1 SOB 1 Group Brand untuk brand item yang dipilih.
578 Dto isDifferentGroupBrandExistsDto = isDifferentGroupBrandExistsByBrandList.execute(new Dto().putList("brandList",
579 brandList));
580
581 if (isDifferentGroupBrandExistsDto.getBoolean("exists")) {
582 throw new CoreException(SalesExceptionConstantsForKtmt.GROUP_BRAND_MUST_BE_SAME_IN_DOC, "Sales Order By Brand");
583 }
584
585 // Jika brandId tdk punya group brand
586 if (isDifferentGroupBrandExistsDto.getBoolean("notFound")) {
587 throw new CoreException(SalesExceptionConstantsForKtmt.CANT_ADD_DETAIL_BRAND_CAUSE_BRAND_HAS_NOT_GROUP_BRAND);
588 }
589 log.debug(" End Cek GroupBrand() : "+DateUtil.dateTimeNow());
590
591 // format nilai amount
592 Double totalAmountSO = nettAmount.doubleValue();
593 NumberFormat formatter = NumberFormat.getNumberInstance();
594 formatter.setMinimumFractionDigits(2) ; // 2 angka di belakang koma
595 String formattedTotalAmount = formatter.format(totalAmountSO);
596
597 // Cek nilai amount dari type SO
598 if(SalesConstantsForKtmt.SO_TYPE_REGULAR.equals(flgTypeSo)
599 || SalesConstantsForKtmt.SO_TYPE_KONSINYASI.equals(flgTypeSo)){
600
601 // Jika merupakan type SO (Regular/Konsinyasi) maka jumlah amountnya harus > 0
602 if(CommonBusinessValidator.compareNumber(totalAmountSO.toString(), "0", CommonBusinessValidator.COMPARE_LESS_EQUAL, "totalAmountSO", "0")){
603 throw new CoreException(SalesExceptionConstantsForKtmt.TOTAL_AMOUNT_NOT_VALID_FOR_THIS_SO_TYPE, formattedTotalAmount);
604 }
605
606 } else if (SalesConstantsForKtmt.SO_TYPE_TRIAL.equals(flgTypeSo)
607 || SalesConstantsForKtmt.SO_TYPE_SAMPEL.equals(flgTypeSo)
608 || SalesConstantsForKtmt.SO_TYPE_REVISI.equals(flgTypeSo)
609 || SalesConstantsForKtmt.SO_TYPE_FOC.equals(flgTypeSo)) {
610
611 // Nilai nya harus 0
612 if(!CommonBusinessValidator.compareNumber(totalAmountSO.toString(), "0", CommonBusinessValidator.COMPARE_EQUAL, "totalAmountSO", "0")){
613 throw new CoreException(SalesExceptionConstantsForKtmt.TOTAL_AMOUNT_NOT_VALID_FOR_THIS_SO_TYPE, formattedTotalAmount);
614 }
615
616 }
617
618 // Cek data SOB mengenai product FOC and Non FOC
619 Dto paramInputExistingDataFOCAndNonFOCDto = new Dto();
620 paramInputExistingDataFOCAndNonFOCDto.put("tenantId", tenantLoginId);
621 paramInputExistingDataFOCAndNonFOCDto.put("soId", id);
622 Dto existingDataFOCAndNonFOC = isSoBrandItemFOCAndNonFOCExistsBySOB.execute(paramInputExistingDataFOCAndNonFOCDto);
623
624 // cek apakah ada data FOC
625 log.debug(" Start Cek existingDataFOCAndNonFOC() : "+DateUtil.dateTimeNow());
626 if (existingDataFOCAndNonFOC.getBoolean("focExists")) {
627
628 // Cek apakah juga ada data non FOC
629 if (existingDataFOCAndNonFOC.getBoolean("nonFocExists")) {
630
631 // Check sub ctgr product data FOC
632 Dto paramInputGetSubCtgrProductDto = new Dto();
633 paramInputGetSubCtgrProductDto.put("tenantId", tenantLoginId);
634 paramInputGetSubCtgrProductDto.put("soId", id);
635 List<Dto> getDataSubCtgrProductFromDataFOCSOBList = getSubCtgrProductListFromDataFOCSalesOrderByBrand.execute(
636 paramInputGetSubCtgrProductDto).getList("subCtgrProductFromDataFocSobList");
637
638 if (getDataSubCtgrProductFromDataFOCSOBList != null && getDataSubCtgrProductFromDataFOCSOBList.size() > 0) {
639
640 log.debug(" prepare looping for data FOC () : "+DateUtil.dateTimeNow());
641 for (Dto itemFromDataFOCDto : getDataSubCtgrProductFromDataFOCSOBList) {
642 Long brandId = Long.valueOf(itemFromDataFOCDto.getString("brandId"));
643 String brandCode = itemFromDataFOCDto.getString("brandCode");
644 String subCtgrProductCode = itemFromDataFOCDto.getString("subCtgrProductCode");
645
646 Dto parameterDto = findParameterByIndex.execute(new Dto().put("code",
647 SalesConstantsForKtmt.SYSTEM_CONFIG_SUB_CTGR_PRODUCT_FOC));
648
649 Dto paramIsSystemConfigExistsByIndex = new Dto();
650 paramIsSystemConfigExistsByIndex.put("tenantId", tenantLoginId);
651 paramIsSystemConfigExistsByIndex.put("parameterId", parameterDto.getLong("id"));
652
653 Dto systemConfigDto = isSystemConfigExistsByIndex.execute(paramIsSystemConfigExistsByIndex);
654 if (systemConfigDto.getBoolean("isTrue")) {
655
656 // Check apakah brand FOC ini valid dijadikan data FOC berdasarkan sub ctgr product
657 Dto paramInputBrandValidForDataFOCDto = new Dto();
658 paramInputBrandValidForDataFOCDto.put("tenantId", tenantLoginId);
659 paramInputBrandValidForDataFOCDto.put("soId", id);
660 paramInputBrandValidForDataFOCDto.put("brandId", brandId);
661 Dto isDataSoBrandValidForDataFOCDto = isSoBrandValidToCreateDataFOC.execute(paramInputBrandValidForDataFOCDto);
662 String valueOfSystemConfig = isDataSoBrandValidForDataFOCDto.getString("valueOfSystemConfig");
663
664 if (!isDataSoBrandValidForDataFOCDto.getBoolean("exists")){
665 throw new CoreException(
666 SalesExceptionConstantsForKtmt.CANT_USE_THIS_BRAND_FOR_DATA_FOC_CAUSE_SUB_CATEGORY_PRODUCT_NOT_VALID,
667 brandCode, subCtgrProductCode, valueOfSystemConfig);
668 }
669
670 }
671
672 }
673 log.debug(" end looping for data FOC () : "+DateUtil.dateTimeNow());
674 }
675 }
676 }
677 log.debug(" Start Cek existingDataFOCAndNonFOC() : "+DateUtil.dateTimeNow());
678
679 log.debug(" Start Cek Data MOU() : "+DateUtil.dateTimeNow());
680 //cek apakah mouId = -99? jika tidak lakukan validasi lanjutan
681 if (!GeneralConstants.NULL_REF_VALUE_LONG.equals(mouId)) {
682
683 //MOU harus exists
684 Dto mouDto = findMouById.execute(new Dto().put("id", mouId));
685 String periodFromMou = mouDto.getString("periodFrom");
686 String periodToMou = mouDto.getString("periodTo");
687
688 // validasi partnerId di SO harus salah satu customer di MOU
689 Dto paramMouDto = new Dto();
690 paramMouDto.put("tenantId", tenantLoginId);
691 paramMouDto.put("ouId", ouId);
692 paramMouDto.put("mouId", mouId);
693 paramMouDto.put("partnerId", partnerId);
694 valMouValidToSalesOrder.execute(paramMouDto);
695
696 //validasi SO harus dibuat dalam rentang waktu periode MOU
697 boolean periodFromBoolean = CommonBusinessValidator.compareDate(docDate, periodFromMou,
698 CommonBusinessValidator.COMPARE_LESS, "Date Sales Order", "Period From MOU");
699 boolean periodToBoolean = CommonBusinessValidator.compareDate(docDate, periodToMou,
700 CommonBusinessValidator.COMPARE_GREATER, "Date Sales Order", "Period To MOU");
701
702 if (periodFromBoolean || periodToBoolean) {
703 throw new CoreException(SalesExceptionConstantsForKtmt.SO_DATE_NOT_VALID_TO_MOU, docDate, periodFromMou,
704 periodToMou);
705 }
706
707 //validasi sisa limit MOU harus mencukupi untuk total Amount SO
708 Dto mouBalanceDto = findMouBalanceById.execute(new Dto().put("id", mouId));
709 Double limitAmount = mouBalanceDto.getDouble("mouBalance");
710 Double usageAmount = mouBalanceDto.getDouble("usageBalance");
711 Calc remainingAmount = new Calc(limitAmount).subtract(usageAmount);
712 Double remaining = remainingAmount.doubleValue();
713 Double totalAmountSOBIncludeTax = nettAmountIncludeTax.doubleValue();
714 boolean limitValidation = CommonBusinessValidator.compareNumber(remaining.toString(), totalAmountSOBIncludeTax.toString(),
715 CommonBusinessValidator.COMPARE_LESS, "Sisa Plafon", "Total So Include Tax");
716
717 // set format
718 String formattedRemaining = formatter.format(remaining);
719 String formattedTotalAmountSOBIncludeTax = formatter.format(totalAmountSOBIncludeTax);
720 if (limitValidation) {
721 throw new CoreException(SalesExceptionConstantsForKtmt.MOU_LIMIT_ARE_INSUFFICIENT, formattedRemaining,
722 formattedTotalAmountSOBIncludeTax);
723 }
724 }
725
726 log.debug(" Start Cek Data PROMO() : "+DateUtil.dateTimeNow());
727 // cek promoId apakah = -99 ? kalau tidak lakukan validasi lanjutan
728 if (!GeneralConstants.NULL_REF_VALUE_LONG.equals(promoId)) {
729 // Promo must exist
730 Dto promoDto = findPromoById.execute(new Dto().put("id", promoId));
731
732 // cek promo harus active dan tenantId nya sama dengan tenantLoginId
733 checkTenant(tenantLoginId, promoDto, "Sales Order By Brand", "Promo");
734 checkActive(promoDto, "Promo");
735
736 // Cek promo harus valid ,brand di promo harus ada yang sama dengan brand di so brand item
737 Dto paramPromoDto = new Dto();
738 paramPromoDto.put("tenantId", tenantLoginId);
739 paramPromoDto.put("promoId", promoId);
740 paramPromoDto.put("flgLaunching", GeneralConstants.NO);
741 paramPromoDto.put("soId", id);
742 valPromoValidToSalesOrder.execute(paramPromoDto);
743
744 }
745
746 log.debug(" Start Cek Data LAUNCHING() : "+DateUtil.dateTimeNow());
747 // cek productLaunchingId apakah = -99 ? kalau tidak lakukan validasi lanjutan
748 if (!GeneralConstants.NULL_REF_VALUE_LONG.equals(productLaunchingId)) {
749 // product launching must exist
750 Dto productLaunchingDto = findPromoById.execute(new Dto().put("id", productLaunchingId));
751
752 // cek product launching harus active dan tenantId nya sama dengan tenantLoginId
753 checkTenant(tenantLoginId, productLaunchingDto, "Sales Order By Brand", "Product Launching");
754 checkActive(productLaunchingDto, "Product Launching");
755
756 // Cek product launching harus valid ,brand di product launching harus ada yang sama dengan brand di so brand item
757 Dto paramProductLaunchingDto = new Dto();
758 paramProductLaunchingDto.put("tenantId", tenantLoginId);
759 paramProductLaunchingDto.put("promoId", productLaunchingId);
760 paramProductLaunchingDto.put("flgLaunching", GeneralConstants.YES);
761 paramProductLaunchingDto.put("soId", id);
762 valPromoValidToSalesOrder.execute(paramProductLaunchingDto);
763
764 }
765
766 log.debug(" Start Check mengenai SOB ini boleh tagging ke Launching dan MOU/ promo dan MOU() : "+DateUtil.dateTimeNow());
767 // Check mengenai SOB ini boleh tagging ke Launching dan MOU/ promo dan MOU
768 Dto paramInputCheckNotValidTaggingDto = new Dto();
769 paramInputCheckNotValidTaggingDto.put("soId", id);
770 paramInputCheckNotValidTaggingDto.put("soDate", docDate);
771 paramInputCheckNotValidTaggingDto.put("productLaunchingId", productLaunchingId);
772 paramInputCheckNotValidTaggingDto.put("promoId", promoId);
773 paramInputCheckNotValidTaggingDto.put("mouId", mouId);
774 Dto isNotValidTaggingForSOBExistsDto = isNotValidTaggingForSOBExists.execute(paramInputCheckNotValidTaggingDto);
775
776 if(isNotValidTaggingForSOBExistsDto.getBoolean("notValidTagLaunchingAndMouExists")){
777 throw new CoreException(SalesExceptionConstantsForKtmt.SOB_CANT_TAGGING_LAUNCHING_AND_MOU);
778 }
779
780 if(isNotValidTaggingForSOBExistsDto.getBoolean("notValidTagPromoAndMouExists")){
781 throw new CoreException(SalesExceptionConstantsForKtmt.SOB_CANT_TAGGING_PROMO_AND_MOU);
782 }
783
784 if (isBrandValidDto.getBoolean("exists") && isQtyBrandValidDto.getBoolean("exists")) {
785 soInfoDto.put("flgAutoSettle", GeneralConstants.YES);
786 this.prepareUpdateAudit(soInfoDto, userLoginId, datetime);
787 } else {
788 soInfoDto.put("flgAutoSettle", GeneralConstants.NO);
789 this.prepareUpdateAudit(soInfoDto, userLoginId, datetime);
790 }
791
792 salesOrderByBrandDto.put("statusDoc", SalesConstants.IN_PROGRESS_TRANSACTION);
793 salesOrderByBrandDto.put("workflowStatus", workflowStatus);
794 salesOrderByBrandDto.put("version", version);
795 this.prepareUpdateAudit(salesOrderByBrandDto, userLoginId, datetime);
796
797 //update status SO
798 Dto soStatusDto = findSoStatusById.execute(new Dto().put("id", id));
799 soStatusDto.put("statusDoc", SalesConstantsForKtmt.IN_PROGRESS_TRANSACTION);
800 this.prepareUpdateAudit(soStatusDto, userLoginId, datetime);
801
802
803 inputDto.put("salesOrderByBrandDto", salesOrderByBrandDto);
804 inputDto.put("brandItemList", brandItemList);
805 inputDto.put("soInfoDto", soInfoDto);
806 inputDto.put("soStatusDto", soStatusDto);
807 inputDto.put("mergeDataStockReservedList", mergeDataStockReservedList);
808
809 log.debug(" end prepare SubmitSalesOrderByBrand() : "+DateUtil.dateTimeNow());
810 return null;
811 }
812
813 @SuppressWarnings("unchecked")
814 @Override
815 public Dto process(Dto inputDto, Dto originalDto) throws Exception {
816 log.debug(" Start process SubmitSalesOrderByBrand() : "+DateUtil.dateTimeNow());
817
818 // Update data table sl_so_brand_item
819 List<Dto> brandItemList = inputDto.getList("brandItemList");
820 if (brandItemList != null && brandItemList.size() > 0) {
821 for (Dto brandItemDto : brandItemList) {
822 SoBrandItem soBrandItem = GsonUtil.fromDto(brandItemDto, SoBrandItem.class);
823 soBrandItem = soBrandItemDao.merge(brandItemDto.getLong("id"), soBrandItem);
824 }
825 }
826
827 // submit sales order by brand
828 Dto salesOrderByBrandDto = inputDto.getDto("salesOrderByBrandDto");
829 SalesOrder salesOrder = GsonUtil.fromDto(salesOrderByBrandDto, SalesOrder.class);
830 salesOrder = salesOrderDao.merge(salesOrderByBrandDto.getLong("id"), salesOrder);
831
832 // Merge sl_so_info
833 Dto soInfoDto = inputDto.getDto("soInfoDto");
834 SoInfo soInfo = GsonUtil.fromDto(soInfoDto, SoInfo.class);
835 soInfo = soInfoDao.merge(soInfoDto.getLong("id"), soInfo);
836
837 //update data SO Status
838 Dto soStatusDto = inputDto.getDto("soStatusDto");
839 SoStatus soStatus = GsonUtil.fromDto(soStatusDto, SoStatus.class);
840 soStatus = soStatusDao.merge(soStatus.getId(), soStatus);
841
842 //Finally update so settlement item & stock reserved
843 List<Dto> mergeDataStockReservedList = inputDto.getList("mergeDataStockReservedList");
844 if (mergeDataStockReservedList != null && mergeDataStockReservedList.size() > 0) {
845
846 log.info(" start mergeDataStockReservedList : "+DateUtil.dateTimeNow());
847 QueryBuilder builderAddReserved = new QueryBuilder();
848 //@formatter:off
849 builderAddReserved.add(" WITH origin_updated_product AS ( ")
850 .add(" UPDATE in_product_balance_stock_reserved A ")
851 .add(" SET qty= (A.qty + B.qty_int), ")
852 .add(" version= (A.version + 1), ")
853 .add(" update_datetime = :updateDatetime, ")
854 .add(" update_user_id = :updateUserId ")
855 .add(" FROM ").add(SalesOrderItem.TABLE_NAME).add(" B ")
856 .add(" WHERE A.product_id = B.product_id ")
857 .add(" AND A.product_status = :productStatus ")
858 .add(" AND A.tenant_id = :tenantId ")
859 .add(" AND A.ou_id = :ouId ")
860 .add(" AND B.so_id = :soId ")
861 .add(" RETURNING A.* ) ")
862 .add(" INSERT INTO in_product_balance_stock_reserved ")
863 .add(" (tenant_id, ou_id, product_id, base_uom_id, product_status, qty, ")
864 .add(" version, create_datetime, create_user_id, update_datetime, update_user_id) ")
865 .add(" SELECT A.tenant_id, :ouId, A.product_id, A.base_uom_id, :productStatus, A.qty_int, ")
866 .add(" :version, :createDatetime, :createUserId, :updateDatetime, :updateUserId ")
867 .add(" FROM ").add(SalesOrderItem.TABLE_NAME).add(" A ")
868 .add(" WHERE A.so_id = :soId ")
869 .add(" AND NOT EXISTS ( ")
870 .add(" SELECT 1 FROM origin_updated_product Z ")
871 .add(" WHERE Z.product_id = A.product_id ")
872 .add(" AND Z.product_status = :productStatus ")
873 .add(" AND Z.tenant_id = :tenantId ")
874 .add(" AND Z.ou_id = :ouId ")
875 .add(" ); ");
876 //@formatter:on
877
878 Query queryAddReserved = productBalanceStockReservedDao.createNativeQuery(builderAddReserved.toString());
879 queryAddReserved.setParameter("tenantId", inputDto.getLong("tenantLoginId"));
880 queryAddReserved.setParameter("ouId", salesOrder.getOuId());
881 queryAddReserved.setParameter("soId", salesOrder.getId());
882 queryAddReserved.setParameter("productStatus", SalesConstantsForKtmt.STATUS_GOOD);
883 queryAddReserved.setParameter("version", SalesConstantsForKtmt.ZERO_REF_VALUE_LONG);
884 queryAddReserved.setParameter("createDatetime", inputDto.getString("datetime"));
885 queryAddReserved.setParameter("createUserId", inputDto.getLong("userLoginId"));
886 queryAddReserved.setParameter("updateDatetime", inputDto.getString("datetime"));
887 queryAddReserved.setParameter("updateUserId", inputDto.getLong("userLoginId"));
888
889 queryAddReserved.executeUpdate();
890 productBalanceStockReservedDao.flush();
891 for(Dto item : mergeDataStockReservedList) {
892 Dto logProductBalanceStockReservedDto = new Dto();
893 this.prepareInsertAudit(logProductBalanceStockReservedDto, inputDto.getLong("userLoginId"), inputDto.getString("datetime"));
894 LogProductBalanceStockReserved logProductBalanceStockReservedEntity = GsonUtil.fromDto(new Dto(), LogProductBalanceStockReserved.class);
895 logProductBalanceStockReservedEntity.setTenantId(inputDto.getLong("tenantLoginId"));
896 logProductBalanceStockReservedEntity.setOuId(salesOrder.getOuId());
897 logProductBalanceStockReservedEntity.setRefDocTypeId(salesOrder.getDocTypeId());
898 logProductBalanceStockReservedEntity.setRefId(salesOrder.getId());
899 logProductBalanceStockReservedEntity.setDocNo(salesOrder.getDocNo());
900 logProductBalanceStockReservedEntity.setDocDate(salesOrder.getDocDate());
901 logProductBalanceStockReservedEntity.setPartnerId(salesOrder.getPartnerId());
902 logProductBalanceStockReservedEntity.setProductId(item.getLong("productId"));
903 logProductBalanceStockReservedEntity.setBaseUomId(item.getLong("baseUomId"));
904 logProductBalanceStockReservedEntity.setProductStatus(SalesConstantsForKtmt.STATUS_GOOD);
905 logProductBalanceStockReservedEntity.setQty(item.getDouble("qtyInt"));
906 logProductBalanceStockReservedEntity.setRemark(SalesConstantsForKtmt.REMARK_SUBMIT_RESERVED_STOCK_SOB);
907 }
908
909 log.debug(" end mergeDataStockReservedList : "+DateUtil.dateTimeNow());
910 }
911
912 // update dan insert ke balance mou dan ke balance mou log jika mouId nya tidak -99
913 if (!GeneralConstants.NULL_REF_VALUE_LONG.equals(inputDto.getLong("mouId"))) {
914
915
916 log.debug(" start update sl_mou_balance : "+DateUtil.dateTimeNow());
917 // Update table sl_mou_balance
918 QueryBuilder builder = new QueryBuilder();
919 builder.add(" WITH summary AS ( ")
920 .add(" SELECT A.so_id, B.mou_id, (SUM (C.nett_brand_amount) + SUM(f_get_tax_amount_after_discount(f_get_gross_amount_after_discount(C.gross_sell_price, C.flg_disc, C.discount_percentage, C.discount_amount, C.qty, 0), C.flg_tax_amount, C.tax_percentage, 0))) AS amount ")
921 .add(" FROM ").add(SalesOrder.TABLE_NAME).add(" A ")
922 .add(" INNER JOIN ").add(SoInfo.TABLE_NAME).add(" B ON A.so_id = B.so_id ")
923 .add(" INNER JOIN ").add(SoBrandItem.TABLE_NAME).add(" C ON A.so_id = C.so_id ")
924 .add(" WHERE A.so_id = :soId ")
925 .add(" AND B.mou_id <> :emptyId ")
926 .add(" GROUP BY A.so_id, B.mou_id ")
927 .add(" ) ")
928 .add(" UPDATE ").add(MouBalance.TABLE_NAME).add(" D ")
929 .add(" SET usage_balance = D.usage_balance + E.amount, ")
930 .add(" version = D.version + 1, ")
931 .add(" update_datetime = :datetime, ")
932 .add(" update_user_id = :userId ")
933 .add(" FROM summary E ")
934 .add(" WHERE D.mou_id = E.mou_id; ");
935
936
937 Query queryUpdateBalanceMou = mouBalanceDao.createNativeQuery(builder.toString());
938 queryUpdateBalanceMou.setParameter("soId", salesOrder.getId());
939 queryUpdateBalanceMou.setParameter("datetime", inputDto.getString("datetime"));
940 queryUpdateBalanceMou.setParameter("userId", inputDto.getLong("userLoginId"));
941 queryUpdateBalanceMou.setParameter("emptyId", GeneralConstants.NULL_REF_VALUE_LONG);
942 queryUpdateBalanceMou.executeUpdate();
943 log.debug(" end update sl_mou_balance : "+DateUtil.dateTimeNow());
944
945 log.debug(" start update sl_mou_balance_log : "+DateUtil.dateTimeNow());
946 // insert ke table sl_mou_balance_log, terkait pengurangan plafon
947 builder = new QueryBuilder();
948 builder.add(" WITH summary AS ( ")
949 .add(" SELECT A.so_id, A.tenant_id, A.ou_id, A.doc_type_id, A.doc_no, A.doc_date, ")
950 .add(" A.partner_id, A.curr_code, B.mou_id, ")
951 .add(" SUM (C.nett_brand_amount) AS amount_brand ")
952 .add(" FROM ").add(SalesOrder.TABLE_NAME).add(" A ")
953 .add(" INNER JOIN ").add(SoInfo.TABLE_NAME).add(" B ON A.so_id = B.so_id ")
954 .add(" INNER JOIN ").add(SoBrandItem.TABLE_NAME).add(" C ON A.so_id = C.so_id ")
955 .add(" WHERE A.so_id = :soId ")
956 .add(" AND B.mou_id <> :emptyId ")
957 .add(" GROUP BY A.so_id, A.tenant_id, A.ou_id, A.doc_type_id, A.doc_no, A.doc_date, ")
958 .add(" A.partner_id, A.curr_code, B.mou_id ")
959 .add(" ) ")
960 .add(" INSERT INTO ").add(MouBalanceLog.TABLE_NAME).add(" ( ")
961 .add(" tenant_id, ou_id, mou_id, ref_doc_type_id, ref_id, ref_doc_no, ref_doc_date, ")
962 .add(" partner_id, curr_code, amount, remark, ")
963 .add(" create_datetime, create_user_id, update_datetime, update_user_id, version) ")
964 .add(" SELECT D.tenant_id, D.ou_id, D.mou_id, D.doc_type_id, D.so_id, D.doc_no, D.doc_date, ")
965 .add(" D.partner_id, D.curr_code, -1*D.amount_brand AS amount, 'Cutting Balance MOU from SO', ")
966 .add(" :datetime, :userId, :datetime, :userId, 0 ")
967 .add(" FROM summary D; ")
968
969 .add(" WITH summary AS ( ")
970 .add(" SELECT A.so_id, A.tenant_id, A.ou_id, A.doc_type_id, A.doc_no, A.doc_date, ")
971 .add(" A.partner_id, A.curr_code, B.mou_id, ")
972 .add(" SUM(f_get_tax_amount_after_discount(f_get_gross_amount_after_discount(C.gross_sell_price, C.flg_disc, C.discount_percentage, C.discount_amount, C.qty, 0), C.flg_tax_amount, C.tax_percentage, 0)) AS amount_tax ")
973 .add(" FROM ").add(SalesOrder.TABLE_NAME).add(" A ")
974 .add(" INNER JOIN ").add(SoInfo.TABLE_NAME).add(" B ON A.so_id = B.so_id ")
975 .add(" INNER JOIN ").add(SoBrandItem.TABLE_NAME).add(" C ON A.so_id = C.so_id ")
976 .add(" WHERE A.so_id = :soId ")
977 .add(" AND B.mou_id <> :emptyId ")
978 .add(" GROUP BY A.so_id, A.tenant_id, A.ou_id, A.doc_type_id, A.doc_no, A.doc_date, ")
979 .add(" A.partner_id, A.curr_code, B.mou_id ")
980 .add(" ) ")
981 .add(" INSERT INTO ").add(MouBalanceLog.TABLE_NAME).add(" ( ")
982 .add(" tenant_id, ou_id, mou_id, ref_doc_type_id, ref_id, ref_doc_no, ref_doc_date, ")
983 .add(" partner_id, curr_code, amount, remark, ")
984 .add(" create_datetime, create_user_id, update_datetime, update_user_id, version) ")
985 .add(" SELECT F.tenant_id, F.ou_id, F.mou_id, F.doc_type_id, F.so_id, F.doc_no, F.doc_date, ")
986 .add(" F.partner_id, F.curr_code, -1*F.amount_tax AS amount, 'Cutting Balance MOU from SO - Tax', ")
987 .add(" :datetime, :userId, :datetime, :userId, 0 ")
988 .add(" FROM summary F; ");
989
990
991 Query queryUpdateBalanceLogMou = mouBalanceLogDao.createNativeQuery(builder.toString());
992 queryUpdateBalanceLogMou.setParameter("soId", salesOrder.getId());
993 queryUpdateBalanceLogMou.setParameter("datetime", inputDto.getString("datetime"));
994 queryUpdateBalanceLogMou.setParameter("userId", inputDto.getLong("userLoginId"));
995 queryUpdateBalanceLogMou.setParameter("emptyId", GeneralConstants.NULL_REF_VALUE_LONG);
996 queryUpdateBalanceLogMou.executeUpdate();
997 log.debug(" end update sl_mou_balance_log : "+DateUtil.dateTimeNow());
998
999 }
1000
1001 log.debug(" end process SubmitSalesOrderByBrand() : "+DateUtil.dateTimeNow());
1002 return new Dto(salesOrder);
1003 }
1004
1005}
1006