@@ -92,13 +92,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.production-completion-1 {
|
.production-completion-1 {
|
||||||
animation: production-completion-1-blinker 5s linear infinite;
|
color: rgba(207, 12, 12, 0.8);
|
||||||
}
|
|
||||||
@keyframes production-completion-1-blinker {
|
// animation: production-completion-1-blinker 1s linear infinite;
|
||||||
50% {
|
|
||||||
background: rgba(207, 12, 12, 0.555);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// @keyframes production-completion-1-blinker {
|
||||||
|
// 50% {
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
.react-resizable {
|
.react-resizable {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
@@ -5,21 +5,25 @@ import { connect } from "react-redux";
|
|||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { selectBreadcrumbs } from "../../redux/application/application.selectors";
|
import { selectBreadcrumbs } from "../../redux/application/application.selectors";
|
||||||
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import GlobalSearch from "../global-search/global-search.component";
|
import GlobalSearch from "../global-search/global-search.component";
|
||||||
import "./breadcrumbs.styles.scss";
|
import "./breadcrumbs.styles.scss";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
breadcrumbs: selectBreadcrumbs,
|
breadcrumbs: selectBreadcrumbs,
|
||||||
|
bodyshop: selectBodyshop,
|
||||||
});
|
});
|
||||||
|
|
||||||
export function BreadCrumbs({ breadcrumbs }) {
|
export function BreadCrumbs({ breadcrumbs, bodyshop }) {
|
||||||
return (
|
return (
|
||||||
<Row className="breadcrumb-container">
|
<Row className="breadcrumb-container">
|
||||||
<Col xs={24} sm={24} md={16}>
|
<Col xs={24} sm={24} md={16}>
|
||||||
<Breadcrumb separator=">">
|
<Breadcrumb separator=">">
|
||||||
<Breadcrumb.Item>
|
<Breadcrumb.Item>
|
||||||
<Link to={`/manage`}>
|
<Link to={`/manage`}>
|
||||||
<HomeFilled />
|
<HomeFilled />{" "}
|
||||||
|
{(bodyshop && bodyshop.shopname && `(${bodyshop.shopname})`) ||
|
||||||
|
""}
|
||||||
</Link>
|
</Link>
|
||||||
</Breadcrumb.Item>
|
</Breadcrumb.Item>
|
||||||
{breadcrumbs.map((item) =>
|
{breadcrumbs.map((item) =>
|
||||||
|
|||||||
@@ -64,9 +64,9 @@ export default function JobBillsTotalComponent({
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const totalPartsSublet = Dinero(totals.parts.parts.total).add(
|
const totalPartsSublet = Dinero(totals.parts.parts.total)
|
||||||
Dinero(totals.parts.sublets.total)
|
.add(Dinero(totals.parts.sublets.total))
|
||||||
);
|
.add(Dinero(totals.additional.additionalCosts));
|
||||||
|
|
||||||
const discrepancy = totalPartsSublet.subtract(billTotals);
|
const discrepancy = totalPartsSublet.subtract(billTotals);
|
||||||
|
|
||||||
|
|||||||
@@ -171,7 +171,12 @@ export function JobChecklistForm({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
console.log(job,{
|
||||||
|
removeFromProduction: true,
|
||||||
|
actual_completion:
|
||||||
|
job && job.actual_completion && moment(job.actual_completion),
|
||||||
|
actual_delivery: job && job.actual_delivery && moment(job.actual_delivery),
|
||||||
|
});
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
title={t("checklist.labels.checklist")}
|
title={t("checklist.labels.checklist")}
|
||||||
@@ -195,21 +200,26 @@ export function JobChecklistForm({
|
|||||||
addToProduction: true,
|
addToProduction: true,
|
||||||
allow_text_message: job.owner && job.owner.allow_text_message,
|
allow_text_message: job.owner && job.owner.allow_text_message,
|
||||||
scheduled_completion:
|
scheduled_completion:
|
||||||
(job && job.scheduled_completion) ||
|
(job &&
|
||||||
(job.labbrs && job.larhrs
|
job.scheduled_completion &&
|
||||||
? moment().businessAdd(
|
moment(job.scheduled_completion)) ||
|
||||||
(job.labhrs.aggregate.sum.mod_lb_hrs +
|
(job &&
|
||||||
job.larhrs.aggregate.sum.mod_lb_hrs) /
|
job.labhrs &&
|
||||||
bodyshop.target_touchtime,
|
job.larhrs &&
|
||||||
"days"
|
moment().businessAdd(
|
||||||
)
|
(job.labhrs.aggregate.sum.mod_lb_hrs ||
|
||||||
: null),
|
0 + job.larhrs.aggregate.sum.mod_lb_hrs ||
|
||||||
scheduled_delivery: job && job.scheduled_delivery,
|
0) / bodyshop.target_touchtime,
|
||||||
|
"days"
|
||||||
|
)),
|
||||||
|
scheduled_delivery: job && moment(job.scheduled_delivery),
|
||||||
}),
|
}),
|
||||||
...(type === "deliver" && {
|
...(type === "deliver" && {
|
||||||
removeFromProduction: true,
|
removeFromProduction: true,
|
||||||
actual_completion: job && job.actual_completion,
|
actual_completion:
|
||||||
actual_delivery: job && job.actual_delivery,
|
job && job.actual_completion && moment(job.actual_completion),
|
||||||
|
actual_delivery:
|
||||||
|
job && job.actual_delivery && moment(job.actual_delivery),
|
||||||
}),
|
}),
|
||||||
...formItems
|
...formItems
|
||||||
.filter((fi) => fi.value)
|
.filter((fi) => fi.value)
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ export default function JobReconciliationModalComponent({ job, bills }) {
|
|||||||
.flat() || [];
|
.flat() || [];
|
||||||
|
|
||||||
const jobLineData = job.joblines.filter(
|
const jobLineData = job.joblines.filter(
|
||||||
(j) => j.part_type !== null && j.part_type !== "PAE"
|
(j) =>
|
||||||
|
(j.part_type !== null && j.part_type !== "PAE") || IsAdditionalCost(j)
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -50,3 +51,20 @@ export default function JobReconciliationModalComponent({ job, bills }) {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function IsAdditionalCost(jobLine) {
|
||||||
|
//May be able to use db_ref here to help.
|
||||||
|
//936012 is Haz Waste Dispoal
|
||||||
|
//936008 is Paint/Materials
|
||||||
|
//936007 is Shop/Materials
|
||||||
|
|
||||||
|
//Remove paint and shop mat lines. They're calculated under rates.
|
||||||
|
const isPaintOrShopMat =
|
||||||
|
jobLine.db_ref === "936008" || jobLine.db_ref === "936007";
|
||||||
|
|
||||||
|
return (
|
||||||
|
(jobLine.lbr_op === "OP13" || //Added to resolve manual job lines coming into other totals because they have no reference.
|
||||||
|
(jobLine.db_ref && jobLine.db_ref.startsWith("9360"))) &&
|
||||||
|
!isPaintOrShopMat
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,9 +8,6 @@ import { DateFormatter } from "../../utils/DateFormatter";
|
|||||||
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const OneCalendarDay = 60 * 60 * 24 * 1000;
|
|
||||||
const Now = new Date();
|
|
||||||
|
|
||||||
export default function ProductionListDate({ record, field, time }) {
|
export default function ProductionListDate({ record, field, time }) {
|
||||||
const [updateAlert] = useMutation(UPDATE_JOB);
|
const [updateAlert] = useMutation(UPDATE_JOB);
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
@@ -72,17 +69,13 @@ export default function ProductionListDate({ record, field, time }) {
|
|||||||
style={{
|
style={{
|
||||||
height: "19px",
|
height: "19px",
|
||||||
}}
|
}}
|
||||||
|
className={
|
||||||
|
!!record[field] && moment().isSame(moment(record[field]), "day")
|
||||||
|
? "production-completion-1"
|
||||||
|
: ""
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<DateFormatter
|
<DateFormatter bordered={false}>{record[field]}</DateFormatter>
|
||||||
bordered={false}
|
|
||||||
className={
|
|
||||||
!!record[field] && new Date(record[field]) - Now < OneCalendarDay
|
|
||||||
? "production-completion-1"
|
|
||||||
: ""
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{record[field]}
|
|
||||||
</DateFormatter>
|
|
||||||
</div>
|
</div>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -262,6 +262,9 @@ export const QUERY_DELIVER_CHECKLIST = gql`
|
|||||||
jobs_by_pk(id: $jobId) {
|
jobs_by_pk(id: $jobId) {
|
||||||
id
|
id
|
||||||
ro_number
|
ro_number
|
||||||
|
actual_completion
|
||||||
|
actual_delivery
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ export function JobsDeliverContainer({
|
|||||||
checklistConfig={
|
checklistConfig={
|
||||||
(data && data.bodyshops_by_pk.deliverchecklist) || {}
|
(data && data.bodyshops_by_pk.deliverchecklist) || {}
|
||||||
}
|
}
|
||||||
|
job={data ? data.jobs_by_pk : {}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</RbacWrapper>
|
</RbacWrapper>
|
||||||
|
|||||||
@@ -1030,6 +1030,7 @@ exports.QUERY_JOB_COSTING_DETAILS = ` query QUERY_JOB_COSTING_DETAILS($id: uuid!
|
|||||||
status
|
status
|
||||||
ca_bc_pvrt
|
ca_bc_pvrt
|
||||||
ca_customer_gst
|
ca_customer_gst
|
||||||
|
dms_allocation
|
||||||
joblines(where: { removed: { _eq: false } }) {
|
joblines(where: { removed: { _eq: false } }) {
|
||||||
id
|
id
|
||||||
db_ref
|
db_ref
|
||||||
@@ -1073,11 +1074,14 @@ exports.QUERY_JOB_COSTING_DETAILS = ` query QUERY_JOB_COSTING_DETAILS($id: uuid!
|
|||||||
actualhrs
|
actualhrs
|
||||||
productivehrs
|
productivehrs
|
||||||
flat_rate
|
flat_rate
|
||||||
|
ciecacode
|
||||||
}
|
}
|
||||||
bodyshop{
|
bodyshop{
|
||||||
id
|
id
|
||||||
md_responsibility_centers
|
md_responsibility_centers
|
||||||
jc_hourly_rates
|
jc_hourly_rates
|
||||||
|
cdk_dealerid
|
||||||
|
pbs_serialnumber
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}`;
|
}`;
|
||||||
@@ -1133,6 +1137,7 @@ exports.QUERY_JOB_COSTING_DETAILS_MULTI = ` query QUERY_JOB_COSTING_DETAILS_MULT
|
|||||||
status
|
status
|
||||||
ca_bc_pvrt
|
ca_bc_pvrt
|
||||||
ca_customer_gst
|
ca_customer_gst
|
||||||
|
dms_allocation
|
||||||
joblines(where: {removed: {_eq: false}}) {
|
joblines(where: {removed: {_eq: false}}) {
|
||||||
id
|
id
|
||||||
db_ref
|
db_ref
|
||||||
@@ -1176,11 +1181,14 @@ exports.QUERY_JOB_COSTING_DETAILS_MULTI = ` query QUERY_JOB_COSTING_DETAILS_MULT
|
|||||||
actualhrs
|
actualhrs
|
||||||
productivehrs
|
productivehrs
|
||||||
flat_rate
|
flat_rate
|
||||||
|
ciecacode
|
||||||
}
|
}
|
||||||
bodyshop {
|
bodyshop {
|
||||||
id
|
id
|
||||||
md_responsibility_centers
|
md_responsibility_centers
|
||||||
jc_hourly_rates
|
jc_hourly_rates
|
||||||
|
cdk_dealerid
|
||||||
|
pbs_serialnumber
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ function GenerateCostingData(job) {
|
|||||||
val.profitcenter_labor || defaultProfits[val.mod_lbr_ty] || "?";
|
val.profitcenter_labor || defaultProfits[val.mod_lbr_ty] || "?";
|
||||||
|
|
||||||
if (laborProfitCenter === "?")
|
if (laborProfitCenter === "?")
|
||||||
console.log("Unknown type", val.mod_lbr_ty);
|
console.log("Unknown type", val.line_desc, val.mod_lbr_ty);
|
||||||
|
|
||||||
const rateName = `rate_${(val.mod_lbr_ty || "").toLowerCase()}`;
|
const rateName = `rate_${(val.mod_lbr_ty || "").toLowerCase()}`;
|
||||||
const laborAmount = Dinero({
|
const laborAmount = Dinero({
|
||||||
@@ -285,11 +285,12 @@ function GenerateCostingData(job) {
|
|||||||
val.profitcenter_part || defaultProfits[val.part_type] || "?";
|
val.profitcenter_part || defaultProfits[val.part_type] || "?";
|
||||||
|
|
||||||
if (partsProfitCenter === "?")
|
if (partsProfitCenter === "?")
|
||||||
console.log("Unknown type", val.part_type);
|
console.log("Unknown type", val.line_desc, val.part_type);
|
||||||
|
|
||||||
if (!partsProfitCenter)
|
if (!partsProfitCenter)
|
||||||
console.log(
|
console.log(
|
||||||
"Unknown cost/profit center mapping for parts.",
|
"Unknown cost/profit center mapping for parts.",
|
||||||
|
val.line_desc,
|
||||||
val.part_type
|
val.part_type
|
||||||
);
|
);
|
||||||
const partsAmount = Dinero({
|
const partsAmount = Dinero({
|
||||||
@@ -298,13 +299,13 @@ function GenerateCostingData(job) {
|
|||||||
.multiply(val.part_qty || 1)
|
.multiply(val.part_qty || 1)
|
||||||
.add(
|
.add(
|
||||||
val.prt_dsmk_m && val.prt_dsmk_m !== 0
|
val.prt_dsmk_m && val.prt_dsmk_m !== 0
|
||||||
? Dinero({ amount: Math.round(val.prt_dsmk_m * 100) })
|
? Dinero({ amount: Math.round(val.prt_dsmk_m * 100) })
|
||||||
: Dinero({
|
: Dinero({
|
||||||
amount: Math.round(val.act_price * 100),
|
amount: Math.round(val.act_price * 100),
|
||||||
})
|
})
|
||||||
.multiply(val.part_qty || 0)
|
.multiply(val.part_qty || 0)
|
||||||
.percentage(Math.abs(val.prt_dsmk_p || 0))
|
.percentage(Math.abs(val.prt_dsmk_p || 0))
|
||||||
.multiply(val.prt_dsmk_p > 0 ? 1 : -1)
|
.multiply(val.prt_dsmk_p > 0 ? 1 : -1)
|
||||||
);
|
);
|
||||||
if (!acc.parts[partsProfitCenter])
|
if (!acc.parts[partsProfitCenter])
|
||||||
acc.parts[partsProfitCenter] = Dinero();
|
acc.parts[partsProfitCenter] = Dinero();
|
||||||
@@ -322,7 +323,7 @@ function GenerateCostingData(job) {
|
|||||||
"?";
|
"?";
|
||||||
|
|
||||||
if (partsProfitCenter === "?") {
|
if (partsProfitCenter === "?") {
|
||||||
console.log("Unknown type", val.part_type);
|
console.log("Unknown type", val.line_desc, val.part_type);
|
||||||
} else {
|
} else {
|
||||||
const partsAmount = Dinero({
|
const partsAmount = Dinero({
|
||||||
amount: Math.round((val.act_price || 0) * 100),
|
amount: Math.round((val.act_price || 0) * 100),
|
||||||
@@ -330,13 +331,13 @@ function GenerateCostingData(job) {
|
|||||||
.multiply(val.part_qty || 1)
|
.multiply(val.part_qty || 1)
|
||||||
.add(
|
.add(
|
||||||
val.prt_dsmk_m && val.prt_dsmk_m !== 0
|
val.prt_dsmk_m && val.prt_dsmk_m !== 0
|
||||||
? Dinero({ amount: Math.round(val.prt_dsmk_m * 100) })
|
? Dinero({ amount: Math.round(val.prt_dsmk_m * 100) })
|
||||||
: Dinero({
|
: Dinero({
|
||||||
amount: Math.round(val.act_price * 100),
|
amount: Math.round(val.act_price * 100),
|
||||||
})
|
})
|
||||||
.multiply(val.part_qty || 0)
|
.multiply(val.part_qty || 0)
|
||||||
.percentage(Math.abs(val.prt_dsmk_p || 0))
|
.percentage(Math.abs(val.prt_dsmk_p || 0))
|
||||||
.multiply(val.prt_dsmk_p > 0 ? 1 : -1)
|
.multiply(val.prt_dsmk_p > 0 ? 1 : -1)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!acc.parts[partsProfitCenter])
|
if (!acc.parts[partsProfitCenter])
|
||||||
@@ -372,21 +373,41 @@ function GenerateCostingData(job) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Is it a DMS Setup?
|
||||||
|
const selectedDmsAllocationConfig =
|
||||||
|
job.bodyshop.md_responsibility_centers.dms_defaults.find(
|
||||||
|
(d) => d.name === job.dms_allocation
|
||||||
|
) || job.bodyshop.md_responsibility_centers.defaults;
|
||||||
|
|
||||||
const billTotalsByCostCenters = job.bills.reduce((bill_acc, bill_val) => {
|
const billTotalsByCostCenters = job.bills.reduce((bill_acc, bill_val) => {
|
||||||
//At the bill level.
|
//At the bill level.
|
||||||
bill_val.billlines.map((line_val) => {
|
bill_val.billlines.map((line_val) => {
|
||||||
//At the bill line level.
|
//At the bill line level.
|
||||||
//console.log("JobCostingPartsTable -> line_val", line_val);
|
if (job.bodyshop.pbs_serialnumber || job.bodyshop.cdk_dealerid) {
|
||||||
if (!bill_acc[line_val.cost_center])
|
if (!bill_acc[selectedDmsAllocationConfig.costs[line_val.cost_center]])
|
||||||
bill_acc[line_val.cost_center] = Dinero();
|
bill_acc[selectedDmsAllocationConfig.costs[line_val.cost_center]] =
|
||||||
|
Dinero();
|
||||||
|
|
||||||
bill_acc[line_val.cost_center] = bill_acc[line_val.cost_center].add(
|
bill_acc[selectedDmsAllocationConfig.costs[line_val.cost_center]] =
|
||||||
Dinero({
|
bill_acc[selectedDmsAllocationConfig.costs[line_val.cost_center]].add(
|
||||||
amount: Math.round((line_val.actual_cost || 0) * 100),
|
Dinero({
|
||||||
})
|
amount: Math.round((line_val.actual_cost || 0) * 100),
|
||||||
.multiply(line_val.quantity)
|
})
|
||||||
.multiply(bill_val.is_credit_memo ? -1 : 1)
|
.multiply(line_val.quantity)
|
||||||
);
|
.multiply(bill_val.is_credit_memo ? -1 : 1)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (!bill_acc[line_val.cost_center])
|
||||||
|
bill_acc[line_val.cost_center] = Dinero();
|
||||||
|
|
||||||
|
bill_acc[line_val.cost_center] = bill_acc[line_val.cost_center].add(
|
||||||
|
Dinero({
|
||||||
|
amount: Math.round((line_val.actual_cost || 0) * 100),
|
||||||
|
})
|
||||||
|
.multiply(line_val.quantity)
|
||||||
|
.multiply(bill_val.is_credit_memo ? -1 : 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
@@ -443,20 +464,38 @@ function GenerateCostingData(job) {
|
|||||||
const ticketTotalsByCostCenter = job.timetickets.reduce(
|
const ticketTotalsByCostCenter = job.timetickets.reduce(
|
||||||
(ticket_acc, ticket_val) => {
|
(ticket_acc, ticket_val) => {
|
||||||
//At the invoice level.
|
//At the invoice level.
|
||||||
if (!ticket_acc[ticket_val.cost_center])
|
|
||||||
ticket_acc[ticket_val.cost_center] = Dinero();
|
|
||||||
|
|
||||||
ticket_acc[ticket_val.cost_center] = ticket_acc[
|
if (job.bodyshop.pbs_serialnumber || job.bodyshop.cdk_dealerid) {
|
||||||
ticket_val.cost_center
|
if (!ticket_acc[selectedDmsAllocationConfig.costs[ticket_val.ciecacode]])
|
||||||
].add(
|
ticket_acc[selectedDmsAllocationConfig.costs[ticket_val.ciecacode]] =
|
||||||
Dinero({
|
Dinero();
|
||||||
amount: Math.round((ticket_val.rate || 0) * 100),
|
|
||||||
}).multiply(
|
ticket_acc[selectedDmsAllocationConfig.costs[ticket_val.ciecacode]] =
|
||||||
ticket_val.flat_rate
|
ticket_acc[selectedDmsAllocationConfig.costs[ticket_val.ciecacode]].add(
|
||||||
? ticket_val.productivehrs || ticket_val.actualhrs || 0
|
Dinero({
|
||||||
: ticket_val.actualhrs || ticket_val.productivehrs || 0
|
amount: Math.round((ticket_val.rate || 0) * 100),
|
||||||
) //Should base this on the employee.
|
}).multiply(
|
||||||
);
|
ticket_val.flat_rate
|
||||||
|
? ticket_val.productivehrs || ticket_val.actualhrs || 0
|
||||||
|
: ticket_val.actualhrs || ticket_val.productivehrs || 0
|
||||||
|
) //Should base this on the employee.
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (!ticket_acc[ticket_val.cost_center])
|
||||||
|
ticket_acc[ticket_val.cost_center] = Dinero();
|
||||||
|
|
||||||
|
ticket_acc[ticket_val.cost_center] = ticket_acc[
|
||||||
|
ticket_val.cost_center
|
||||||
|
].add(
|
||||||
|
Dinero({
|
||||||
|
amount: Math.round((ticket_val.rate || 0) * 100),
|
||||||
|
}).multiply(
|
||||||
|
ticket_val.flat_rate
|
||||||
|
? ticket_val.productivehrs || ticket_val.actualhrs || 0
|
||||||
|
: ticket_val.actualhrs || ticket_val.productivehrs || 0
|
||||||
|
) //Should base this on the employee.
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return ticket_acc;
|
return ticket_acc;
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user