add store receiving categories and fixed account select field required

po-online-status
usama.jameel 2025-06-10 10:37:17 +05:00
parent a0aa80ba8c
commit d6a9c6a87c
9 changed files with 177 additions and 19 deletions

View File

@ -28,21 +28,18 @@ public class StoreItemDao {
private static final String INSERT_QUERY = String.format(
"INSERT INTO %s (" +
"id, item_id, sku, barcode, job_card_id, created_at, created_by, " +
"finish_item_id, account_id, bundle_id" +
"finish_item_id, account_id, bundle_id, reject_reason" +
") VALUES (" +
":id, :item_id, :sku, :barcode, :job_card_id, :created_at, :created_by, " +
":finish_item_id, :account_id, :bundle_id" +
":finish_item_id, :account_id, :bundle_id, :reject_reason" +
") ON DUPLICATE KEY UPDATE " +
"item_id = VALUES(item_id), sku = VALUES(sku), barcode = VALUES(barcode), " +
"job_card_id = VALUES(job_card_id), created_at = VALUES(created_at), created_by = VALUES(created_by), " +
"finish_item_id = VALUES(finish_item_id), account_id = VALUES(account_id), bundle_id = VALUES(bundle_id)",
"finish_item_id = VALUES(finish_item_id), account_id = VALUES(account_id), bundle_id = VALUES(bundle_id), reject_reason = VALUES(reject_reason)",
TABLE_NAME
);
private static final String SELECT_BY_DATE_AND_IDs = String.format(
"SELECT COUNT(*) FROM %s WHERE (:start_date IS NULL OR created_at >= :start_date) AND created_at <= :end_date AND id IN (:ids)",
TABLE_NAME
);
private static final String SELECT_BY_DATE_AND_IDs = String.format("SELECT COUNT(*) FROM %s WHERE (:start_date IS NULL OR created_at >= :start_date) AND created_at <= :end_date AND id IN (:ids)", TABLE_NAME);
public StoreItemDao(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
@ -59,7 +56,8 @@ public class StoreItemDao {
.addValue("created_by", item.getCreatedBy())
.addValue("finish_item_id", item.getFinishedItemId())
.addValue("account_id", item.getAccountId())
.addValue("bundle_id", item.getBundleId());
.addValue("bundle_id", item.getBundleId())
.addValue("reject_reason", item.getRejectedReason());
}
public StoreItem find(long id) {

View File

@ -21,6 +21,7 @@ public class StoreItemRowMapper implements RowMapper<StoreItem> {
item.setFinishedItemId(rs.getLong("finish_item_id"));
item.setAccountId(rs.getLong("account_id"));
item.setBundleId(rs.getLong("bundle_id"));
item.setRejectedReason(rs.getString("reject_reason"));
return item;
}
}

View File

@ -6,6 +6,7 @@ public class FinishedItemWrapper {
private String qaStatus;
private Long accountId;
private String rejectReason;
private List<FinishedItem> items;
@ -33,6 +34,14 @@ public class FinishedItemWrapper {
this.accountId = accountId;
}
public String getRejectReason() {
return rejectReason;
}
public void setRejectReason(String rejectReason) {
this.rejectReason = rejectReason;
}
@Override
public String toString() {
return "FinishedItemWrapper{" +

View File

@ -18,6 +18,7 @@ public class StoreItem implements InventoryArtifact {
private long finishedItemId;
private long bundleId;
private long accountId;
private String rejectedReason;
@Override
@ -122,4 +123,29 @@ public class StoreItem implements InventoryArtifact {
public void setAccountId(long accountId) {
this.accountId = accountId;
}
public String getRejectedReason() {
return rejectedReason;
}
public void setRejectedReason(String rejectedReason) {
this.rejectedReason = rejectedReason;
}
@Override
public String toString() {
return "StoreItem{" +
"id=" + id +
", itemId=" + itemId +
", sku='" + sku + '\'' +
", barcode='" + barcode + '\'' +
", jobCardId=" + jobCardId +
", createdAt=" + createdAt +
", createdBy='" + createdBy + '\'' +
", finishedItemId=" + finishedItemId +
", bundleId=" + bundleId +
", accountId=" + accountId +
", rejectedReason='" + rejectedReason + '\'' +
'}';
}
}

View File

@ -741,7 +741,7 @@ public class InventoryService {
if (finishedItem.getQaStatus().equalsIgnoreCase("REJECT")) {
// create OUT and IN transactions for FI
StoreItem storeItem = (createStoreItems(finishedItem));
StoreItem storeItem = (createStoreItems(finishedItem, wrapper.getRejectReason()));
storeItem.setId(storeItemDao.save(storeItem));
if (lastInvTransaction != null) {
// OUT
@ -751,7 +751,7 @@ public class InventoryService {
// IN
createInventoryTransactionLeg(transaction, storeItem, toAccount, InventoryTransactionLeg.Type.IN.name(), InventoryArtifactType.STORED_ITEM.name());
}
finishedItem.setIsSegregated(false);
finishedItem.setIsSegregated(true);
finishedItem.setStore(true);
storeItems.add(storeItem);
}
@ -788,7 +788,7 @@ public class InventoryService {
return packagingItems;
}
private StoreItem createStoreItems(FinishedItem finishedItem) {
private StoreItem createStoreItems(FinishedItem finishedItem, String reason) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
StoreItem storeItem = new StoreItem();
storeItem.setItemId(finishedItem.getItemId());
@ -799,6 +799,7 @@ public class InventoryService {
storeItem.setBarcode(finishedItem.getBarcode());
storeItem.setCreatedAt(LocalDateTime.now());
storeItem.setCreatedBy(authentication.getName());
storeItem.setRejectedReason(reason);
return storeItem;
}
}

View File

@ -76,7 +76,8 @@
let app = new Vue({
el : '#packagingApp',
data : {
items : []
items : [],
reason: '',
},
methods : {
onItemSelect: function (id, item) {
@ -90,6 +91,18 @@
const uniqueIds = new Set(ids);
return ids.length !== uniqueIds.size;
},
submitWithRejectReason: function (reason) {
this.reason = reason;
this.$nextTick(() => {
const form = document.getElementById('packagingApp');
if (form.checkValidity()) {
form.submit();
} else {
form.reportValidity();
}
});
}
},
mounted : function () {
console.log( this.$accounts )

View File

@ -86,11 +86,16 @@
return ids.length !== uniqueIds.size;
},
submitWithQaStatus: function (status) {
this.QaStatus = status;
this.$nextTick(() => {
document.getElementById('qcForm').submit();
});
}
this.QaStatus = status;
this.$nextTick(() => {
const form = document.getElementById('qcForm');
if (form.checkValidity()) {
form.submit();
} else {
form.reportValidity();
}
});
}
},
mounted: function () {

View File

@ -0,0 +1,96 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
/* Custom CSS for full height and center alignment of span */
.vertical-divider {
display: flex;
justify-content: center; /* Center horizontally */
align-items: center; /* Center vertically */
}
.vertical-divider span {
display: inline-block;
width: 1px;
background-color: #dee2e6;
height: 100%; /* Take full height of the parent div */
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-sm-12">
<table th:if="${#lists.size(transactions) != 0 && #lists != null }" class="table table-bordered font-sm mb-4" data-account-tables>
<thead>
<tr>
<th>Cut To Pack</th>
<th>Knitting</th>
<th>Dying</th>
</tr>
</thead>
<tbody>
<tr th:each="transaction : ${transactions}" th:object="${transaction}">
<td th:text="*{id}"></td>
<td th:text="*{itemId}"></td>
<td th:text="*{sku}"></td>
</tr>
</tbody>
</table>
<h5 th:if="${#lists.size(transactions) == 0}" class="mt-2">No Inventory Transactions found.</h5>
</div>
</div>
</div>
<div th:replace="_fragments :: page-footer-scripts"></div>
<script th:inline="javascript">
// Initialize DataTables for each individual table
$('table[data-account-tables]').each(function () {
const $table = $(this);
// Prevent reinitializing if already done
if (!$.fn.DataTable.isDataTable($table)) {
$table.DataTable({
pageLength: 5,
searching: true,
lengthChange: false,
processing: false,
dom: `
<'row'<'col-sm-5'B><'col-sm-7'f>>
<'row'<'col-sm-12't>>
<'row'<'col-sm-5'i><'col-sm-7'p>>`,
buttons: [{
extend: 'excel',
text: '',
className: 'bi bi-file-earmark-spreadsheet btn-sm d-none' // Keep it hidden
}]
});
}
});
(async function () {
const $selectAllCheckBox = $('[data-checkbox-all]');
$selectAllCheckBox.change(function () {
if ($selectAllCheckBox.prop('checked')) {
// When parent checkbox is checked, check all child checkboxes
$('[name="parent-doc-type-ids"]').each(function () {
let $this = $(this);
$this.prop('checked', true);
});
} else {
// When parent checkbox is unchecked, uncheck all child checkboxes
$('[name="parent-doc-type-ids"]').each(function () {
let $this = $(this);
$this.prop('checked', false);
});
}
});
})(jQuery)
</script>
</body>
</html>

View File

@ -21,6 +21,7 @@
v-on:finished-item-select="onItemSelect">
</search-item>
</div>
<input type="hidden" name="rejectReason" v-model="reason">
<div class="col-sm-3 form-group">
<label>Store Account</label>
<select class="form-control" name="accountId" th:field="*{accountId}" required>
@ -40,8 +41,16 @@
></finish-item-table>
</div>
<div class="alert alert-danger" v-if="hasDuplicates()">Duplicate Item Selected</div>
<button class="btn btn-primary" type="submit" v-bind:disabled="hasDuplicates()">Submit</button>
<a th:href="@{/packaging/receive-inventory}" class="btn btn-light">Cancel</a>
<button class="btn btn-primary mr-2" type="button" :disabled="hasDuplicates() || items.length === 0"
@click="submitWithRejectReason('Cut To Pack')">Cut To Pack
</button>
<button class="btn btn-danger mr-2" type="button" :disabled="hasDuplicates() || items.length === 0"
@click="submitWithRejectReason('Knitting')">Knitting
</button>
<button class="btn btn-danger mr-2" type="button" :disabled="hasDuplicates() || items.length === 0"
@click="submitWithRejectReason('Dying')">Dying
</button>
<a th:href="@{/store/receive-inventory}" class="btn btn-light">Cancel</a>
</form>
<script th:inline="javascript">
window.ctp.accounts = [[${accounts}]];