import React, { useEffect, useState } from 'react'; import { StyleSheet, View, Text, Dimensions, TextInput, FlatList, TouchableOpacity, Alert, BackHandler, Modal, ImageBackground, Image } from 'react-native'; import { Picker } from '@react-native-picker/picker'; import { RootStackParamList } from '@/types'; import { useNavigation, NavigationProp, useFocusEffect } from '@react-navigation/native'; import { currency } from '@/components/Helper'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { cfg, generateUUID } from '@/components/lib/cfg'; import { DB } from '@/components/lib/db'; import CustomPicker from '@/components/native/dropdown'; import { Ionicons } from '@expo/vector-icons'; // Optional for adding icons import config from '../../components/data/config.json'; import InvoiceScreen from '@/components/pageComponent/invoice'; import TimeLive from '@/components/Time'; import { color } from 'react-native-elements/dist/helpers'; var width = Dimensions.get('window').width; var height = Dimensions.get('window').height; const ProductCard = ({ item, onSlopChange, onBalChange, onBoxChange }: { item: { id: number; name: string; price: number; slop: number; bal: number; box: number }; onSlopChange: (id: number, value: string) => void; onBalChange: (id: number, value: string) => void; onBoxChange: (id: number, value: string) => void; }) => { return ( {item.name} Rp{currency(item.price*10, 0)} DOS onBoxChange(item.id, text)} /> BAL onBalChange(item.id, text)} /> SLOP onSlopChange(item.id, text)} /> ); }; const App = () => { const [employeeData, setEmployeeData] = useState({ name: '', work_email: '', work_phone: '' }); const [products, setProducts] = useState([]); const [alamat,SetAlamat] = useState('-'); const [loaderStatus, setLoaderStatus] = useState(false); const [salesName, setSalesName] = useState('-') const [sendData, setSendData] = useState({ invoice: {}, dataPilihan :{}}) const [invoice , setInvoice] = useState(false) const navigation = useNavigation>(); useFocusEffect( React.useCallback(() => { const onBackPress = () => { console.log(invoice) if (invoice == true) { setInvoice(false); } else { navigation.navigate('home') } return true; // Prevent default behavior (exit app) }; BackHandler.addEventListener('hardwareBackPress', onBackPress); navigation.setOptions({ headerLeft: () => null }); // Remove back button return () => { BackHandler.removeEventListener('hardwareBackPress', onBackPress); }; }, [navigation,invoice, setInvoice]) ); const ToInsert = function (array: any, table: any, wht: any) { array = array ? array : []; wht = wht ? wht : []; table = table ? table : "example"; let s = array; if (s.length > 0) { var y = Object.keys(s[0]); var x = ''; x += 'INSERT INTO '; x += table; x += '('; x += y.map(function (u) { return ` ${u} ` }).join(','); x += ')'; x += '\n'; x += 'SELECT '; x += y.map(function (g) { return `a.${g}`; }); x += ' FROM ('; x += s.map(function (w: any) { var f = ` SELECT `; f += y.map(function (q) { if (w[q] != null) { if (typeof w[q] === 'boolean') { return `${w[q]} AS ${q}`; } if (typeof w[q] === 'number') { return `${w[q]} AS ${q}`; } if (typeof w[q] === 'object' && w[q] == null) { return `null AS ${q}`; } if (w[q] == 'timestamp') { return `now() AS ${q}`; } return `'${w[q].toString().replace(/\"/g, "\\\"")}' AS ${q}`; } else { return `'-' AS ${q}`; } }).join(","); return f; }).join("\n UNION ALL \n") x += ') a'; if (Array.isArray(wht) && wht.length > 0) { x += ` LEFT JOIN ${table} ON ` x += wht.map(function (whtx) { return ` ${table}.${whtx} = a.${whtx} `; }).join(" AND "); x += ` WHERE `; x += wht.map(function (whtx) { return ` ${table}.${whtx} IS NULL `; }).join(" AND "); } return x; } else { return []; } }; useEffect(()=>{ (async function(){ let data : any = cfg.dataPilihan.product; let y = data.map((d:any, i:any)=>{ return { id: d.id, name: d.name, sku:'-', price: Number(d.list_price), slop:0, bal:0, box:0 } }); setProducts(y); })(); },[]) const [isChanged, setIsChanged] = useState(false); const handleSlopChange = (id:any, value:any) => { setProducts( products.map((product:any) => product.id === id ? { ...product, slop: parseInt(value) || 0 } : product ) ); setIsChanged(true); }; const handleBalChange = (id:any, value:any) => { setProducts( products.map((product:any) => product.id === id ? { ...product, bal: parseInt(value) || 0 } : product ) ); setIsChanged(true); }; const handleBoxChange = (id:any, value:any) => { setProducts( products.map((product:any) => product.id === id ? { ...product, box: parseInt(value) || 0 } : product ) ); setIsChanged(true); }; const calculateTotal = () => { return products.reduce((total:any, product:any) => { return total + ((product.slop*10) + (product.bal*100) + (product.box*500)) * product.price; }, 0); }; const renderProductItem = (props:any) => ( ); const [selectedValue, setSelectedValue] = useState(''); const options = cfg.dataPilihan.customer.length > 0 ? [{ label: "Select Customer", value:""}].concat(cfg.dataPilihan.customer.map((data:any, i:number)=>{ return { label: data.name, value: typeof data.id === 'number' ? data.id.toString(): data.id }; })) : [ { label: 'CAHAYA UTAMA', value: 'CAHAYA UTAMA' }, { label: 'MERTASARI', value: 'MERTASARI' }, { label: 'PRIMA JAYA', value: 'PRIMA JAYA' }, { label: 'ARIS Dalung', value: 'ARIS Dalung' }, { label: 'JAYA KERTI Ubung', value: 'JAYA KERTI Ubung' }, { label: 'JAYA KERTI Gatsu', value: 'JAYA KERTI Gatsu' }, { label: 'AGUS WISNU', value: 'AGUS WISNU' }, { label: 'SINAR WANGI', value: 'SINAR WANGI' }, { label: 'CRYSTAL', value: 'CRYSTAL' }, ]; useEffect(() => { getEmployeeData(); }, []); const getEmployeeData = async () => { try { const jsonValue = await AsyncStorage.getItem('login'); if (jsonValue !== null) { const data = JSON.parse(jsonValue); const sales = data[0]; setEmployeeData(data[0]); setSalesName(sales.name.toUpperCase()) } } catch (e) { console.error(e); } }; const mapTax = function(){ } const mapsDataOrder = function(data:any){ cfg.invoice.token_access = generateUUID() return [{ company_id: data.company_id ? data.company_id : 1, partner_id: data.partner_id ? data.partner_id : null, partner_invoice_id: data.partner_id ? data.partner_id : null, partner_shipping_id: data.partner_id ? data.partner_id : null, user_id : data.user_id ? data.user_id : null , team_id : data.team_id ? data.team_id : 1 , create_uid: data.create_uid ? data.create_uid : null, write_uid : data.create_uid ? data.create_uid : 1 , name : data.name ? data.name : null , state: 'draft' , access_token: cfg.invoice.token_access, client_order_ref: data.email ? data.email :null , invoice_status: data.invoice_status ? data.invoice_status :"no" , validity_date: data.validity_date ? data.validity_date :"timestamp" , currency_id: data.currency_id ? data.currency_id :12 , currency_rate: data.currency_rate ? data.currency_rate :1.0 , amount_untaxed: data.amount_untaxed ? data.amount_untaxed :null , amount_tax: data.amount_tax ? data.amount_tax :null , amount_total: data.amount_total ? data.amount_total :null , amount_to_invoice: data.amount_to_invoice ? data.amount_to_invoice :null , locked: data.locked ? data.locked :false , require_signature: data.require_signature ? data.require_signature :true , require_payment: data.require_payment ? data.require_payment :false , create_date: data.create_date ? data.require_payment :"timestamp" , date_order: data.date_order ? data.date_order :"timestamp" , write_date: data.write_date ? data.write_date :"timestamp" , prepayment_percent: data.prepayment_percent ? data.prepayment_percent :1 , warehouse_id: data.warehouse_id ? data.warehouse_id :1 , picking_policy: data.picking_policy ? data.picking_policy :"direct" , x_studio_sales_man: data.x_studio_sales_man ? data.x_studio_sales_man : null }]; } const mapsDataOrderLine = function(data:any){ return Array.isArray(data) ? data.map((d,i)=>{ return { order_id: d.order_id? d.order_id : null, sequence : d.sequence ? d.sequence : 10, company_id: d.company_id ? d.company_id : 1, currency_id: d.currency_id ? d.currency_id : 12, order_partner_id: d.order_partner_id ? d.order_partner_id : null, salesman_id: d.salesman_id ? d.salesman_id : 2, product_id: d.product_id ? d.product_id : null, product_uom: d.product_uom ? d.product_uom : 27, create_uid: d.create_uid ? d.create_uid : null, write_uid: d.write_uid ? d.write_uid : null, state: d.state ? d.state : "sale", qty_delivered_method: d.qty_delivered_method ? d.qty_delivered_method : "stock_move", invoice_status: d.invoice_status ? d.invoice_status : "no", name: d.name ? d.name : null, product_uom_qty: d.product_uom_qty ? d.product_uom_qty : 0, price_unit: d.price_unit ? d.price_unit : 0, discount: d.discount ? d.discount : 0, price_subtotal: d.price_subtotal ? d.price_subtotal : 0, price_total: d.price_total ? d.price_total : 0, price_reduce_taxexcl: d.price_reduce_taxexcl ? d.price_reduce_taxexcl : 0, price_reduce_taxinc: d.price_reduce_taxinc ? d.price_reduce_taxinc : 0, qty_delivered: d.qty_delivered ? d.qty_delivered : 0, qty_invoiced: d.qty_invoiced ? d.qty_invoiced : 0, qty_to_invoice: d.qty_to_invoice ? d.qty_to_invoice : 0, untaxed_amount_invoiced: d.untaxed_amount_invoiced ? d.untaxed_amount_invoiced : 0, untaxed_amount_to_invoice: d.untaxed_amount_to_invoice ? d.untaxed_amount_to_invoice : 0, is_downpayment: d.is_downpayment ? d.is_downpayment : false, create_date: d.create_date ? d.create_date : 'timestamp', write_date: d.write_date ? d.write_date : 'timestamp', price_tax: d.price_tax ? d.price_tax : 0, product_packaging_qty: d.product_packaging_qty ? d.product_pakaging_qty : 0, customer_lead: d.customer_lead ? d.customer_lead : 0, is_service: d.is_service ? d.is_service : false, planning_hours_planned: d.planning_hours_planned ? d.planning_hours_planned : 0, planning_hours_to_plan: d.planning_hours_to_plan ? d.planning_hours_to_plan : 0, } }):[]; } function getFormattedDate() { const today = new Date(); const day = String(today.getDate()).padStart(2, '0'); const month = String(today.getMonth() + 1).padStart(2, '0'); // Months are zero-based const year = today.getFullYear(); return `${day}/${month}/${year}`; } const saveAction = async ()=>{ const activeTax = 1; const [tax] = cfg.dataPilihan.tax.filter((s:any)=> s.id == activeTax ); const taxValue = Number(tax?.amount) / 100; const sales: any = await AsyncStorage.getItem('login') const [salesman]: any = JSON.parse(sales); let [cus] = cfg.dataPilihan.customer.filter((data:any)=> data.id == selectedValue ); if(!cus){ Alert.alert("Warning", "Please select a customer first!"); return true; } cus = cus ? cus:null; let totalHarga = 0; let amount_untaxed = 0; let amount_tax = 0; let amount_total = 0; let amount_to_invoice = 0; // fungsi penghiungan tax const taxCount = function(){ return { nilaiTax : (taxValue * totalHarga), nilaiTotalAndTax : ((1+taxValue) * totalHarga), nilaiTotal : totalHarga } } const perbandinganHarga = { pcs : 1, slop : 10, bal : 100, box : 500 } let getProduk = products.filter((s:any)=>{ if(s.box != 0 || s.bal != 0 || s.slop != 0 ){ return s; } }); products.forEach((n: any, i: any) => { let box = n.box * perbandinganHarga.box * n.price; let bal = n.bal * perbandinganHarga.bal * n.price; let slop = n.slop * perbandinganHarga.slop * n.price; totalHarga += (box + bal + slop); }); if (totalHarga === 0) { Alert.alert("Warning", "silahkan isi total pesanan terlebih dahulu!"); return true; } setLoaderStatus(true) const [newName]: any = await DB(` SELECT 'S' || LPAD((name + 1)::text, 5, '0') as name FROM ( SELECT split_part(name, 'S', -1)::integer AS name FROM sale_order ORDER BY name DESC LIMIT 1 ) a; `); const name = newName.name; // default user_id menggunakan administrator const user_id = 2; // default company_id administrator const company_id = 1; let dataNilai = taxCount(); amount_untaxed = dataNilai.nilaiTotal amount_tax = dataNilai.nilaiTax; amount_total = dataNilai.nilaiTotalAndTax; try{ (async function SimpanData(){ let dataOrder = mapsDataOrder({ user_id: user_id, company_id: company_id, partner_id: cus ? cus.id : 0, create_uid: salesman ? salesman.id : null, email: salesman ? salesman.work_email : '', amount_untaxed: amount_untaxed, amount_tax: amount_tax, amount_total: amount_total, amount_to_invoice: amount_total, name: name, x_studio_sales_man: salesman?.id }); cfg.invoice.sales_order = dataOrder; cfg.invoice.times = getFormattedDate(); setSendData((function (d: any) { d.invoice.sales_order = cfg.invoice.sales_order; d.invoice.times = cfg.invoice.times; d.dataPilihan = cfg.dataPilihan; return d; })(sendData)); let data: any = await DB( ToInsert(dataOrder, "sale_order", []) ); let ds: any = await DB(`SELECT id as newId FROM sale_order ORDER BY id DESC LIMIT 1`); let newProduct:any = []; getProduk.forEach((c:any)=>{ // dos if(c.box > 0){ newProduct.push({ id: c.id, name: c.name, price: c.price * 500, product_uom: 30, qty : c.box, sku : c.sku }); } // bal if(c.bal > 0){ newProduct.push({ id: c.id, name: c.name, price: c.price * 100, product_uom: 29, qty : c.bal, sku : c.sku }); } // slop if(c.slop > 0){ newProduct.push({ id: c.id, name: c.name, price: c.price * 10, product_uom: 28, qty : c.slop, sku : c.sku }); } }); let dataItem: any = mapsDataOrderLine(newProduct.map((s: any) => { return { company_id: company_id, product_id: s.id, salesman_id : salesman.id, order_partner_id: cus.id, create_uid: salesman.id, write_uid: salesman.id, name : s.name, product_uom: s.product_uom, product_uom_qty : s.qty, price_unit: s.price, price_subtotal: s.qty * s.price, price_total: (s.qty * s.price) * (1 + taxValue), price_reduce_taxexcl: s.price, price_reduce_taxinc: s.price * (taxValue), price_tax: s.price * (1+taxValue), order_id: Number(ds[0].newid) } })); cfg.invoice.sales_order_line = dataItem; setSendData((function(d:any){ d.invoice.sales_order_line = dataItem; return d; })(sendData)); // console.log("Produk :", ToInsert(dataItem, "sale_order_line",[])); let data2:any = await DB( ToInsert(dataItem, "sale_order_line", []) ); let saveTax:any = await DB(`SELECT * FROM sale_order_line WHERE order_id = ${ds[0].newid}`) let saveTaxItem = saveTax.map(function(item:any){ return { sale_order_line_id : item.id, account_tax_id : 1 } }); let data3: any = await DB( ToInsert(saveTaxItem, "account_tax_sale_order_line_rel", []) ); console.log("Order :", "----------------------------------------"); setLoaderStatus(false) clearForm() setInvoice(true); })(); }catch(e){ console.log(e); setLoaderStatus(false) } } const clearForm = () => { setSelectedValue('') setProducts( products.map((product: any) => ({ ...product, slop: 0, bal: 0, box: 0 })) ); } const callNumber = () => { console.log("call") } let c:any = 1; return ( <> { invoice?<> :<> {loaderStatus === true ? <> :<>} SALES {salesName} CUSTOMER Address {selectedValue && selectedValue.toLocaleLowerCase() != 'select customer' ? <> {(function(data:any){ if(Array.isArray(data)){ let [d] = data; return d.street ? d.street:'-'; } return '-' })(cfg.dataPilihan.customer.filter((pop: any) => pop.id == selectedValue)) } : <> - } item.id.toString()} contentContainerStyle={{ paddingHorizontal: 16, paddingBottom: 100 }} /> Total: Rp{currency(calculateTotal(), 0)} { saveAction() }}> Save } ); }; const styles = StyleSheet.create({ loader:{ position:'absolute', zIndex:1, height:'100%', width:'100%', backgroundColor: config.color.primary, flexDirection :'row', justifyContent:'center', alignItems:'center' }, container: { position:'relative', flex: 1, backgroundColor: '#f0f0f0', paddingTop: 0, overflow: "hidden" }, alamat:{ fontSize: 14, color:'white' }, header: { position: "absolute", top: 0, left: 0, height: 200, width: "100%", flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, }, informationContainer: { width: width, height: 200, marginLeft: 16, marginTop: 16, }, name: { fontSize: 20, marginBottom: 5, fontWeight: 'bold', color: '#ffffff', }, label: { fontSize: 12, color: '#ffffff', marginBottom: 5, marginTop: 10, fontWeight:'700' }, productList: { flex: 1, paddingTop: 5, }, productCard: { backgroundColor: '#fff', borderRadius: 8, shadowColor: '#000', shadowOpacity: 0.2, shadowOffset: { width: 0, height: 2 }, shadowRadius: 4, padding: 16, marginBottom: 16, }, productRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', }, productInfo: { flex: 1, marginRight: 16, }, productName: { fontSize: 18, fontWeight: 'bold', marginBottom: 4, }, productPrice: { fontSize: 16, fontWeight: 'bold', color: 'red', }, textSatuan: { fontSize: 16, fontWeight:'600' }, satuan: { fontWeight: 'bold', height: 40, width: 75, backgroundColor: '#2563eb', borderRadius: 4, justifyContent: 'center', alignItems: 'center', marginTop: 10, marginBottom: 5, paddingVertical: 5 }, input: { height: 40, borderColor: '#ccc', borderWidth: 1, borderRadius: 8, paddingHorizontal: 10, marginTop: 10, marginBottom: 10, textAlign: 'center', }, bottomContainer: { position: 'absolute', bottom: 0, left: 0, right: 0, padding: 15, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', backgroundColor: '#2563eb', }, totalText: { fontSize: 14, fontWeight: 'bold', color: '#fff', }, totalPrice: { fontSize: 24, fontWeight: 'bold', color: '#fff', }, continueButton: { backgroundColor: '#93C854', borderRadius: 8, paddingVertical: 10, paddingHorizontal: 20, alignItems: 'center', }, continueButtonText: { color: '#fff', fontSize: 18, fontWeight: 'bold', }, }); export default App;