opt:优化ERP同步锁,单据推送暂停问题

This commit is contained in:
2025-03-12 13:09:31 +08:00
parent d816474903
commit da8ebb188d
10 changed files with 99 additions and 97 deletions

View File

@@ -27,6 +27,7 @@ public class DictConstantPool {
,"qty","申请数量" ,"qty","申请数量"
,"plan_qty","计划数量" ,"plan_qty","计划数量"
,"assign_qty","已领数量" ,"assign_qty","已领数量"
,"actual_qty","实际数量"
,"bar_code","条码" ,"bar_code","条码"
,"unit_id","单位" ,"unit_id","单位"
,"pcsn","批次" ,"pcsn","批次"

View File

@@ -30,7 +30,7 @@ import java.util.stream.Collectors;
public class ErpServiceUtils { public class ErpServiceUtils {
@Resource @Resource
ErpSec erpSec; ErpSec erpSec;
private final ReentrantLock lock = new ReentrantLock();
/** /**
@@ -50,48 +50,39 @@ public class ErpServiceUtils {
if (StringUtils.isBlank(query.getFormId())) { if (StringUtils.isBlank(query.getFormId())) {
throw new BadRequestException("参数异常"); throw new BadRequestException("参数异常");
} }
boolean islock = lock.tryLock();
List<Object> result = new ArrayList<>(); List<Object> result = new ArrayList<>();
try { try {
if (islock) { String jsonString = JSON.toJSONString(query);
String jsonString = JSON.toJSONString(query); K3CloudApi cloudApi = getCloudApi();
K3CloudApi cloudApi = getCloudApi(); List<List<Object>> lists = cloudApi.executeBillQuery(jsonString);
List<List<Object>> lists = cloudApi.executeBillQuery(jsonString); for (List<Object> list : lists) {
for (List<Object> list : lists) { for (Object r : list) {
for (Object r : list) { String fid = r.toString();
String fid = r.toString(); if (StringUtils.isEmpty(fid)) {
if (StringUtils.isEmpty(fid)) { log.error("单据同步失败,没有找到FID");
log.error("单据同步失败,没有找到FID"); continue;
continue; }
} try {
try { OperateParam param = new OperateParam();
OperateParam param = new OperateParam(); param.setId(fid);
param.setId(fid); OperatorResult view = cloudApi.view(query.getFormId(), param);
OperatorResult view = cloudApi.view(query.getFormId(), param); RepoStatus status = view.getResult().getResponseStatus();
RepoStatus status = view.getResult().getResponseStatus(); if (status.isIsSuccess()) {
if (status.isIsSuccess()) { new ArrayList<>();
new ArrayList<>(); result.add(view.getResult().getResult());
result.add(view.getResult().getResult()); } else {
} else { ArrayList<RepoError> errors = status.getErrors();
ArrayList<RepoError> errors = status.getErrors(); log.error("查询ID [{}] 时出现异常: {}", fid, errors.stream().map(RepoError::getMessage).collect(Collectors.joining(",")));
log.error("查询ID [{}] 时出现异常: {}", fid, errors.stream().map(RepoError::getMessage).collect(Collectors.joining(",")));
}
} catch (Exception e) {
log.error("查询ID [{}] 时出现异常: {}", fid, e.getMessage());
} }
} catch (Exception e) {
log.error("查询ID [{}] 时出现异常: {}", fid, e.getMessage());
} }
} }
} else {
throw new BadRequestException("系统正在自动同步ERP单据正占用接口资源请稍后再试1");
} }
return JSON.parseArray(JSON.toJSONString(result));
} catch (Exception ex) { } catch (Exception ex) {
throw new BadRequestException(ex.getMessage()); throw new BadRequestException(ex.getMessage());
} finally {
if (lock.isLocked() && lock.isHeldByCurrentThread()) {
lock.unlock();
}
} }
return JSON.parseArray(JSON.toJSONString(result));
} }
/** /**
@@ -101,10 +92,8 @@ public class ErpServiceUtils {
if (StringUtils.isBlank(query.getFormId())) { if (StringUtils.isBlank(query.getFormId())) {
throw new BadRequestException("参数异常"); throw new BadRequestException("参数异常");
} }
boolean islock = lock.tryLock();
List<JSONObject> result = new ArrayList<>(); List<JSONObject> result = new ArrayList<>();
try { try {
if (islock) {
String jsonString = JSON.toJSONString(query); String jsonString = JSON.toJSONString(query);
K3CloudApi cloudApi = getCloudApi(); K3CloudApi cloudApi = getCloudApi();
List<List<Object>> lists = cloudApi.executeBillQuery(jsonString); List<List<Object>> lists = cloudApi.executeBillQuery(jsonString);
@@ -114,15 +103,8 @@ public class ErpServiceUtils {
jsonObject.put("erpCounts",list.get(1)); jsonObject.put("erpCounts",list.get(1));
result.add(jsonObject); result.add(jsonObject);
} }
} else {
throw new BadRequestException("系统正在自动同步ERP单据正占用接口资源请稍后再试2");
}
} catch (Exception ex) { } catch (Exception ex) {
throw new BadRequestException(ex.getMessage()); throw new BadRequestException(ex.getMessage());
} finally {
if (lock.isLocked() && lock.isHeldByCurrentThread()) {
lock.unlock();
}
} }
return result; return result;
} }

View File

@@ -115,7 +115,7 @@ public class BmFormStrucController {
@GetMapping("/getParentFormTypes") @GetMapping("/getParentFormTypes")
public ResponseEntity<Object> getParentFormTypes(){ public ResponseEntity<Object> getParentFormTypes(){
//参数判读,参数解析,调用参数入库 //参数判读,参数解析,调用参数入库
QueryWrapper<BmFormStruc> queryWrapper = new QueryWrapper<BmFormStruc>().select("form_type", "form_name").isNull("parent_id").groupBy("form_type"); QueryWrapper<BmFormStruc> queryWrapper = new QueryWrapper<BmFormStruc>().select("form_type", "form_name").isNull("parent_id").isNotNull("sort").groupBy("form_type").orderByAsc("sort");;
List<Map<String, Object>> select = iBmFormStrucService.listMaps(queryWrapper); List<Map<String, Object>> select = iBmFormStrucService.listMaps(queryWrapper);
List<Map> list = new ArrayList<>(); List<Map> list = new ArrayList<>();
for (Map<String, Object> map : select) { for (Map<String, Object> map : select) {
@@ -128,7 +128,7 @@ public class BmFormStrucController {
//参数判读,参数解析,调用参数入库 //参数判读,参数解析,调用参数入库
QueryWrapper<BmFormStruc> queryWrapper = new QueryWrapper<BmFormStruc>().select("form_type", "form_name").isNull("parent_id").groupBy("form_type").orderByAsc("sort"); QueryWrapper<BmFormStruc> queryWrapper = new QueryWrapper<BmFormStruc>().select("form_type", "form_name").isNull("parent_id").groupBy("form_type").orderByAsc("sort");
if (StringUtils.isNotEmpty(desc)){ if (StringUtils.isNotEmpty(desc)){
queryWrapper.like("form_desc",desc); queryWrapper.like("form_desc",desc).isNotNull("sort");
} }
List<Map<String, Object>> select = iBmFormStrucService.listMaps(queryWrapper); List<Map<String, Object>> select = iBmFormStrucService.listMaps(queryWrapper);
List<Map> list = new ArrayList<>(); List<Map> list = new ArrayList<>();

View File

@@ -106,6 +106,11 @@ public class BmFormStruc implements Serializable {
*/ */
private String plan_qty; private String plan_qty;
/**
* 实际数量
*/
private String actual_qty;
/** /**
* 已领取数量 * 已领取数量
*/ */

View File

@@ -156,6 +156,11 @@ public class SchBaseTaskServiceImpl extends ServiceImpl<SchBaseTaskMapper, SchBa
List<MdPbVehicleMater> vehicleMaterList = iMdPbVehicleMaterService.list(new QueryWrapper<MdPbVehicleMater>() List<MdPbVehicleMater> vehicleMaterList = iMdPbVehicleMaterService.list(new QueryWrapper<MdPbVehicleMater>()
.eq("vehicle_code", task.getVehicle_code()) .eq("vehicle_code", task.getVehicle_code())
.eq("is_delete", false)); .eq("is_delete", false));
if (ObjectUtils.isEmpty(vehicleMaterList)) {
throw new BadRequestException("当前任务未找到组盘信息");
}
if (StringUtils.isEmpty(vehicleMaterList.get(0).getProc_inst_id())) {
FlowContinueEvent continueEvent = new FlowContinueEvent(vehicleMaterList.get(0).getProc_inst_id(), null, null);
if (ObjectUtil.isEmpty(vehicleMaterList)) { if (ObjectUtil.isEmpty(vehicleMaterList)) {
throw new BadRequestException("任务完成失败,到载具物料信息: " + task.getVehicle_code()); throw new BadRequestException("任务完成失败,到载具物料信息: " + task.getVehicle_code());
} }

View File

@@ -83,6 +83,11 @@ public class PmFormData implements Serializable {
*/ */
private BigDecimal assign_qty; private BigDecimal assign_qty;
/**
* 实际数量
*/
private BigDecimal actual_qty;
/** /**
* 单位 * 单位
*/ */

View File

@@ -125,6 +125,10 @@ public class PmFormDataDto implements Serializable {
* 已分配数量 * 已分配数量
*/ */
private BigDecimal assign_qty; private BigDecimal assign_qty;
/**
* 实际数量
*/
private BigDecimal actual_qty;
/** /**
* 单位 * 单位

View File

@@ -353,6 +353,8 @@ public class PmFormDataServiceImpl extends ServiceImpl<PmFormDataMapper, PmFormD
for (PmFormDataDto child : children) { for (PmFormDataDto child : children) {
String childProductArea = child.getForm_data().getString("product_area"); String childProductArea = child.getForm_data().getString("product_area");
child.setProduct_area(childProductArea); child.setProduct_area(childProductArea);
BigDecimal total = child.getPlan_qty().subtract(child.getAssign_qty().add(child.getActual_qty() == null ? BigDecimal.ZERO : child.getActual_qty()));
child.setQty(total.compareTo(BigDecimal.ZERO) > 0 ? total : BigDecimal.ZERO);
} }
} }
dataDto.setChildren(children); dataDto.setChildren(children);
@@ -415,6 +417,8 @@ public class PmFormDataServiceImpl extends ServiceImpl<PmFormDataMapper, PmFormD
child.setSto_qty(BigDecimal.valueOf(maps.stream().mapToInt(a -> a.getSto_qty().intValue()).sum())); child.setSto_qty(BigDecimal.valueOf(maps.stream().mapToInt(a -> a.getSto_qty().intValue()).sum()));
child.setPcsn(""); child.setPcsn("");
} }
BigDecimal total = child.getPlan_qty().subtract(child.getAssign_qty().add(child.getActual_qty() == null ? BigDecimal.ZERO : child.getActual_qty()));
child.setQty(total.compareTo(BigDecimal.ZERO) > 0 ? total : BigDecimal.ZERO);
} }
pmFormDataDto.setChildren(childs); pmFormDataDto.setChildren(childs);
return pmFormDataDto; return pmFormDataDto;

View File

@@ -180,11 +180,11 @@ public class SyncErpBillsScheduleService {
* 手动同步 * 手动同步
*/ */
private String manualSyncData(String mappingJson, String formType, Boolean dtlSplit, String code, String start, String end) { private String manualSyncData(String mappingJson, String formType, Boolean dtlSplit, String code, String start, String end) {
boolean islock = lock.tryLock();
Map errorMsg = new HashMap<>(); Map errorMsg = new HashMap<>();
try { try {
if (islock) {
//单据同步总数 //单据同步总数
JSONArray result; JSONArray result;
// 获取当前日期 // 获取当前日期
String timeEnd = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); String timeEnd = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
@@ -211,15 +211,8 @@ public class SyncErpBillsScheduleService {
} else { } else {
return "同步成功,共计" + result.size() + ""; return "同步成功,共计" + result.size() + "";
} }
}else {
throw new BadRequestException("3系统正在自动同步ERP单据正占用接口资源请稍后再试3");
}
} catch (Exception ex) { } catch (Exception ex) {
throw new BadRequestException(ex.getMessage()); throw new BadRequestException(ex.getMessage());
} finally {
if (lock.isLocked() && lock.isHeldByCurrentThread()) {
lock.unlock();
}
} }
} }
@@ -303,21 +296,18 @@ public class SyncErpBillsScheduleService {
//单据明细 //单据明细
if (StringUtils.isBlank(f.getCode())) { if (StringUtils.isBlank(f.getCode())) {
PmFormData existDtlData = formDataService.getOne(new QueryWrapper<PmFormData>().eq("id", id).select("qty")); PmFormData existDtlData = formDataService.getOne(new QueryWrapper<PmFormData>().eq("id", id).select("qty"));
//existDtlData.getQty().compareTo(BigDecimal.ZERO) > 0||f.getPlan_qty().compareTo(f.getAssign_qty()) > 0
if (existDtlData.getQty() != null) { if (existDtlData.getQty() != null) {
if (existDtlData.getQty().compareTo(BigDecimal.ZERO) > 0) {
formDataService.update(new LambdaUpdateWrapper<PmFormData>() formDataService.update(new LambdaUpdateWrapper<PmFormData>()
.set(PmFormData::getMaterial_id, f.getMaterial_id()) .set(PmFormData::getMaterial_id, f.getMaterial_id())
.set(PmFormData::getQty, f.getQty())
.set(PmFormData::getUnit_id, f.getUnit_id()) .set(PmFormData::getUnit_id, f.getUnit_id())
.set(PmFormData::getForm_data, JSON.toJSONString(f.getForm_data())) .set(PmFormData::getForm_data, JSON.toJSONString(f.getForm_data()))
.set(PmFormData::getPlan_qty, f.getPlan_qty()) .set(PmFormData::getPlan_qty, f.getPlan_qty())
.set(PmFormData::getTaxPrice, f.getActual_qty())
.set(PmFormData::getBar_code, f.getBar_code()) .set(PmFormData::getBar_code, f.getBar_code())
.set(PmFormData::getUpdate_name, DateUtil.now()) .set(PmFormData::getUpdate_name, DateUtil.now())
.set(PmFormData::getUpdate_name, SecurityUtils.getCurrentNickName()) .set(PmFormData::getUpdate_name, SecurityUtils.getCurrentNickName())
.eq(PmFormData::getId, id)); .eq(PmFormData::getId, id));
} }
}
} }
} else { } else {
//单据明细 //单据明细

View File

@@ -86,12 +86,12 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<rrOperation/> <rrOperation />
</el-form> </el-form>
</div> </div>
<!--如果想在工具栏加入更多按钮可以使用插槽方式 slot = 'left' or 'right'--> <!--如果想在工具栏加入更多按钮可以使用插槽方式 slot = 'left' or 'right'-->
<crudOperation :permission="permission"/> <crudOperation :permission="permission" />
<!--表单组件--> <!--表单组件-->
<el-dialog <el-dialog
:close-on-click-modal="false" :close-on-click-modal="false"
@@ -118,8 +118,8 @@
</el-form-item> </el-form-item>
<el-form-item label="所属区域" prop="region_code"> <el-form-item label="所属区域" prop="region_code">
<el-select <el-select
disabled
v-model="form.region_code" v-model="form.region_code"
disabled
placeholder="请选择" placeholder="请选择"
style="width: 370px;" style="width: 370px;"
> >
@@ -131,13 +131,13 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="点位编码" prop="code"> <el-form-item label="点位编码" prop="code">
<el-input v-model="form.code" disabled style="width: 370px;"/> <el-input v-model="form.code" disabled style="width: 370px;" />
</el-form-item> </el-form-item>
<el-form-item label="点位名称" prop="name"> <el-form-item label="点位名称" prop="name">
<el-input v-model="form.name" disabled style="width: 370px;"/> <el-input v-model="form.name" disabled style="width: 370px;" />
</el-form-item> </el-form-item>
<el-form-item label="载具编码" prop="vehicle_code"> <el-form-item label="载具编码" prop="vehicle_code">
<el-input v-model="form.vehicle_code" clearable style="width: 370px;"/> <el-input v-model="form.vehicle_code" clearable style="width: 370px;" />
</el-form-item> </el-form-item>
<el-form-item label="绑定/解绑" prop="priority"> <el-form-item label="绑定/解绑" prop="priority">
<el-select <el-select
@@ -185,7 +185,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="是否启用" prop="is_used"> <el-form-item label="是否启用" prop="is_used">
<el-switch v-model="form.is_used" :active-value=true :inactive-value=false /> <el-switch v-model="form.is_used" :active-value="true" :inactive-value="false" />
</el-form-item> </el-form-item>
<el-form-item v-show="pointTypesDialogList.length > 0" label="点位类型" prop="device_point_type"> <el-form-item v-show="pointTypesDialogList.length > 0" label="点位类型" prop="device_point_type">
<el-select <el-select
@@ -204,16 +204,16 @@
</el-form-item> </el-form-item>
<el-form-item label="位置" prop="point_location"> <el-form-item label="位置" prop="point_location">
<el-input v-model="form.point_location" clearable style="width: 370px;"/> <el-input v-model="form.point_location" clearable style="width: 370px;" />
</el-form-item> </el-form-item>
<!-- <el-form-item label="优先级" prop="priority">--> <!-- <el-form-item label="优先级" prop="priority">-->
<!-- <el-input v-model="form.priority" clearable style="width: 370px;"/>--> <!-- <el-input v-model="form.priority" clearable style="width: 370px;"/>-->
<!-- </el-form-item>--> <!-- </el-form-item>-->
<el-form-item label="表单数据" prop="form_data"> <el-form-item label="表单数据" prop="form_data">
<el-input type="textarea" v-model="form.form_data" clearable style="width: 370px;"/> <el-input v-model="form.form_data" type="textarea" clearable style="width: 370px;" />
</el-form-item> </el-form-item>
<el-form-item label="备注"> <el-form-item label="备注">
<el-input v-model="form.remark" style="width: 370px;" rows="2" type="textarea"/> <el-input v-model="form.remark" style="width: 370px;" rows="2" type="textarea" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
@@ -230,10 +230,10 @@
style="width: 100%;" style="width: 100%;"
@selection-change="crud.selectionChangeHandler" @selection-change="crud.selectionChangeHandler"
> >
<el-table-column type="selection" width="55"/> <el-table-column type="selection" width="55" />
<el-table-column prop="code" label="点位编码" sortable width="120" show-overflow-tooltip /> <el-table-column prop="code" label="点位编码" sortable width="120" show-overflow-tooltip />
<el-table-column prop="name" label="点位名称" width="150" sortable show-overflow-tooltip/> <el-table-column prop="name" label="点位名称" width="150" sortable show-overflow-tooltip />
<el-table-column prop="region_code" label="区域编码" min-width="120" show-overflow-tooltip/> <el-table-column prop="region_code" label="区域编码" min-width="120" show-overflow-tooltip />
<el-table-column prop="point_type" label="点位类型"> <el-table-column prop="point_type" label="点位类型">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.point_type == '1' ? '满货架' : '空货架' }} {{ scope.row.point_type == '1' ? '满货架' : '空货架' }}
@@ -249,16 +249,22 @@
{{ scope.row.is_used == '1' ? '是' : '否' }} {{ scope.row.is_used == '1' ? '是' : '否' }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="vehicle_code" label="载具编码" min-width="120" show-overflow-tooltip/> <el-table-column prop="vehicle_code" label="载具编码" min-width="120" show-overflow-tooltip />
<!-- <el-table-column prop="priority" label="优先级"/>--> <!-- <el-table-column prop="priority" label="优先级"/>-->
<!-- <el-table-column prop="point_location" label="位置" min-width="120" show-overflow-tooltip/>--> <!-- <el-table-column prop="point_location" label="位置" min-width="120" show-overflow-tooltip/>-->
<!-- <el-table-column prop="group_code" label="点位组编码" min-width="120" show-overflow-tooltip/>--> <!-- <el-table-column prop="group_code" label="点位组编码" min-width="120" show-overflow-tooltip/>-->
<!-- <el-table-column prop="form_data" label="表单数据" min-width="120" show-overflow-tooltip/>--> <!-- <el-table-column prop="form_data" label="表单数据" min-width="120" show-overflow-tooltip/>-->
<el-table-column prop="remark" label="备注" :min-width="flexWidth('remark',crud.data,'备注')" show-overflow-tooltip/> <el-table-column
<el-table-column prop="create_name" label="创建人"/> prop="remark"
<el-table-column prop="create_time" label="创建时间" width="150"/> label="备注"
<el-table-column prop="update_name" label="修改人" width="100"/> :min-width="flexWidth('remark' +
<el-table-column prop="update_time" label="修改时间" width="150"/> '',crud.data,'备注')"
show-overflow-tooltip
/>
<el-table-column prop="create_name" label="创建人" />
<el-table-column prop="create_time" label="创建时间" width="150" />
<el-table-column prop="update_name" label="修改人" width="100" />
<el-table-column prop="update_time" label="修改时间" width="150" />
<el-table-column <el-table-column
v-permission="[]" v-permission="[]"
label="操作" label="操作"
@@ -275,14 +281,14 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
<!--分页组件--> <!--分页组件-->
<pagination/> <pagination />
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import crudPoint, {changeActive} from './point' import crudPoint, { changeActive } from './point'
import CRUD, {crud, form, header, presenter} from '@crud/crud' import CRUD, { crud, form, header, presenter } from '@crud/crud'
import rrOperation from '@crud/RR.operation' import rrOperation from '@crud/RR.operation'
import crudOperation from '@crud/CRUD.operation' import crudOperation from '@crud/CRUD.operation'
import udOperation from '@crud/UD.operation' import udOperation from '@crud/UD.operation'
@@ -311,8 +317,8 @@ const defaultForm = {
export default { export default {
name: 'Point', name: 'Point',
dicts: ['storagevehicle_type', 'd_lock_type', 'SCH_TASK_TYPE_DTL', 'point_location', 'product_area'], dicts: ['storagevehicle_type', 'd_lock_type', 'SCH_TASK_TYPE_DTL', 'point_location', 'product_area'],
statusEnums: ['LOCK','REGION_INFO','POINT_TYPE','BIND_TYPE'], statusEnums: ['LOCK', 'REGION_INFO', 'POINT_TYPE', 'BIND_TYPE'],
components: {pagination, crudOperation, rrOperation, udOperation}, components: { pagination, crudOperation, rrOperation, udOperation },
mixins: [presenter(), header(), form(defaultForm), crud()], mixins: [presenter(), header(), form(defaultForm), crud()],
cruds() { cruds() {
return CRUD({ return CRUD({
@@ -326,7 +332,7 @@ export default {
download: false, download: false,
reset: true reset: true
}, },
crudMethod: {...crudPoint}, crudMethod: { ...crudPoint },
query: { query: {
product_area: 'A2' product_area: 'A2'
} }
@@ -343,19 +349,19 @@ export default {
permission: {}, permission: {},
rules: { rules: {
code: [ code: [
{required: true, message: '点位编码不能为空', trigger: 'blur'} { required: true, message: '点位编码不能为空', trigger: 'blur' }
], ],
name: [ name: [
{required: true, message: '点位名称不能为空', trigger: 'blur'} { required: true, message: '点位名称不能为空', trigger: 'blur' }
], ],
point_type: [ point_type: [
{required: true, message: '点位类型不能为空', trigger: 'blur'} { required: true, message: '点位类型不能为空', trigger: 'blur' }
], ],
priority: [ priority: [
{required: true, message: '绑定或解绑操作不能为空', trigger: 'blur'} { required: true, message: '绑定或解绑操作不能为空', trigger: 'blur' }
], ],
lock_type: [ lock_type: [
{required: true, message: '锁定类型不能为空', trigger: 'blur'} { required: true, message: '锁定类型不能为空', trigger: 'blur' }
] ]
} }
} }
@@ -415,7 +421,7 @@ export default {
this.crud.notify('操作成功', CRUD.NOTIFICATION_TYPE.SUCCESS) this.crud.notify('操作成功', CRUD.NOTIFICATION_TYPE.SUCCESS)
this.crud.toQuery() this.crud.toQuery()
}) })
}, }
} }
} }
</script> </script>