既に同じ車がレンタルされている場合の処理をしたい
前提
Ruby on railsを用いて、車のレンタル機能を開発しております。
レンタル画面(car_logs/take)、返却画面(car_logs/return)、車使用履歴画面(car_logs)がある。
db/schema.rb
create_table "car_logs", comment: "車使用履歴", force: :cascade do |t|
t.bigint "car_id", comment: "車id"
t.bigint "line_id", comment: "ラインid"
t.datetime "take_datetime", comment: "レンタル日時"
t.bigint "take_user_id", comment: "レンタル日時"
t.datetime "return_datetime", comment: "返却日時"
t.bigint "return_user_id", comment: "返却日時"
t.integer "before_weight", comment: "使用前重量"
t.integer "after_weight", comment: "使用後重量"
t.integer "used_weight", comment: "使用量"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["car_id"], name: "index_paintcan_logs_on_paintcan_id"
end
create_table "cars", comment: "車", force: :cascade do |t|
t.datetime "arrival_datetime", comment: "入荷日時"
t.string "product_number", comment: "品番"
t.integer "weight", comment: "重量"
t.bigint "location_id", comment: "ロケーションid"
t.bigint "create_user_id", comment: "作成者id"
t.bigint "update_user_id", comment: "更新者id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
実現したいこと
レンタル画面で持ち出し登録した際に、既に同じ車が別のラインでレンタルされている場合は、自動で返却処理がなされるようにしたい
そのために車使用履歴から既に同じ自転車が別のラインでレンタルされている場合という条件式を記述したい
発生している問題・エラーメッセージ
既に同じ車が別のラインでレンタルされていることを検知できない
該当のソースコード
app/controllers/car_logs/takes_controller.rb
def create
car_logs = []
ActiveRecord::Base.transaction do
car_logs_params.each do |car_log_params|
car_log = CarLog.new(car_log_params)
car_log.take_datetime = params[:take_datetime] || Time.current
car_log.take_user_id = params[:take_user_id]
car_log.line_id = params[:line_id]
car_log.created_by(current_user)
end
raise ActiveRecord::Rollback unless success
end
end
app/views/car_logs/takes/show.html.slim
//入力フォーム 2つのVue.jsで定義
#app(v-cloak)
= form_with(url: car_logs_take_path) do |f|
car-logs-form(
v-model='carLogs'
now=Time.current.iso8601[0..18]
:current-user='currentUser'
:last-line='line'
:production-schedule='productionSchedule'
)
= f.submit //持ち出し登録ボタン ここをクリックしたときの処理を追加したい
= javascript_packs_with_chunks_tag 'car_logs/takes/show'
app/javascript/components/car_logs/takes/Form.vue
<template lang='pug'>
div
.d-flex.justify-content-between
.form-group
.form-inline
.form-group
label ライン
LineSelect(
name='line_id'
v-model='lineId'
:line.sync='line'
required
)
.form-group
label レンタル者
UserSelect(
name='take_user_id'
v-model='takeUserId'
:user.sync='takeUser'
required
)
div
button.btn.btn-info(type='button' @click='add(null)') 追加
.table-sticky.max-vh-60(ref='recordsContainer')
table.table.table-form.table-striped.table-bordered
thead
tr
th RFID
th 品番
th ロット番号
th 重量(g)
th 製品
th
tbody
template(v-for='(record, index) in records')
CarLogRow(
ref='detailRows'
:name='`car_logs[${index}]`'
:key='record.key'
:record='records[index]'
:date='datetime'
@remove='remove'
@insert='insert(index)'
)
</template>
<script>
import {v4 as uuid} from 'uuid'
import CarLogRow from './CarLogRow'
import LineSelect from '~/components/LineSelect'
import UserSelect from '~/components/UserSelect'
const newRecord = () => {
return {
key: uuid(),
beforeWeight: null,
product: null,
paintNumber: null,
}
}
export default {
components: {
carLogRow,
},
model: {
prop: 'records',
},
props: {
records: {
type: Array,
},
now: {
type: String,
},
currentUser: {
type: Object,
},
lastLine: {
type: Object,
},
productionSchedule: {
type: Object
},
},
data(){
return {
datetime: this.now,
lineId: this.lastLine?.id,
line: this.lastLine,
takeUserId: this.currentUser.id,
takeUser: this.currentUser,
bPaint: this.production.bPaint,
tPaint: this.production.tPaint,
Number: this.production.Number,
}
},
async mounted(){
this.records.forEach((record) => {
record.key = uuid()
})
if(this.records.length === 0 ){
if(this.bPaint == null && this.tPaint == null){
this.add(null)
}
else{
if (this.bPaint != null){
this.add(this.bPaint)
}
if (this.tPaint != null){
this.add(this.tPaint)
}
}
}
await this.$nextTick()
this.$refs.detailRows[0].focus()
},
methods: {
async add(paint){
let newRecort = newRecord()
newRecort = {product: this.Number, paint: paint}
this.records.push(newRecort)
await this.$nextTick()
scrollToBottom(this.$refs.recordsContainer)
},
async insert(index){
arrayInsert(this.records, newRecord(), index + 1)
await this.$nextTick()
this.$refs.detailRows.at(-1).focus()
},
remove(record){
arrayDelete(this.records, record)
if(this.records.length === 0){
this.add(null)
}
},
},
}
</script>
app/javascript/components/car_logs/takes/CarLogRow.vue
<template lang="pug">
tr(@keypress.stop='onKeypress')
td
input.form-control(
ref='defaultFocusInput'
type='text'
v-model='record.rfid'
@change='onRfidChange'
required
)
input(
type='hidden'
v-model='car.id'
:name='`${name}[car_id]`'
)
td {{car.Number}}
td {{car.lotNumber}}
td
input.form-control(
type='number'
v-model.number='record.beforeWeight'
:name='`${name}[before_weight]`'
step='any'
required
)
td
TextField.w-100(
v-model='record.product'
:name='`${name}[product]`'
:autocomplete='products'
@focus='onProductFocus'
)
td.text-nowrap
button.btn.btn-warning(type='button' @click='remove(record)') 削除
</template>
<script>
import axios from "axios";
import insertCommand from "~/lib/event/insertCommand";
function checkProductNumber(currentPaintNumber, loadedPaintNumber) {
if (currentPaintNumber == null || currentPaintNumber === "") {
return true;
} else {
if (currentPaintNumber !== loadedPaintNumber) {
const ask = window.confirm(
`品番が一致しません。`
);
return ask;
} else {
return true;
}
}
}
export default {
model: {
prop: "record"
},
props: {
name: {
type: String
},
record: {
type: Object
},
date: {
type: String
},
currentRfId: {
type: Number
}
},
data() {
return {
car: {},
products: []
};
},
async mounted() {
this.car = { Number: this.record.paint, lotNumber: "" };
},
methods: {
focus() {
this.$refs.defaultFocusInput.focus();
},
onKeypress(e) {
if (insertCommand(e)) {
this.$emit("insert");
}
},
remove(record) {
this.$emit("remove", record);
},
async onRfidChange(e) {
const input = e.target;
const id = this.record.rfid;
try {
const result = await axios.get(`/api/web/cars/${id}`);
console.log(result.data);
if (
checkNumber(
this.car.Number,
result.data.Number
)
) {
this.car = result.data;
input.setCustomValidity("");
this.currentRfId = id;
} else {
this.record.rfid = this.currentRfId;
}
} catch (e) {
this.car = {};
input.setCustomValidity("");
}
},
async onProductFocus(e) {
this.products = [];
const params = {
date: this.date
};
const result = await axios.get("/api/web/productions", {
params
});
console.log(result);
this.products = result.data.map(
it => `${it.productNumber} ${it.productName}`
);
}
}
};
</script>
試したこと
持ち出し登録した際に、既に同じものが別のラインで持ち出されている場合であることを検知するために以下の記述をしたが、登録しようとしているものと同じcar_idをまず、検知できていないため、何か気づくことがあれば教えて頂けると幸いです。
app/controllers/car_logs/takes_controller.rb
def create
省略
car_ids = CarLog.find(&:car_id)
take_datetimes =CarLog.find(&:take_datetime)
return_datetimes = CarLog.find(&:return_datetime)
line_ids = CarLog.find(&:line_id)
if car_ids.present?
logger.debug("登録しようとしているものと同じcar_idがある")
if take_datetimes.present? && return_datetimes.nil?
logger.debug("レンタル日時のみあって、返却日時がないデータは存在する")
if line_ids.present?
logger.debug("登録しようとしているラインと異なる")
logger.debug("返却処理を行い、再度登録する")
end
end
else
logger.debug("通常通り登録する")
end
end
補足情報(FW/ツールのバージョンなど)
バージョン情報
Rails 6.1.4.7
ruby 3.1.2
0